var value; var A = function() { setTimeout(function() { value = 10; }, 200); } var B = function() { console.log(value); }那么,现在如果我们运行 A();B(); 我们将在控制台看到输出为 undefined . 之所以会这样是因为 A 函数使用了异步方式设置 value 。我们能做的就是传一个回调函数给A,并让函数A在执行完后执行回调函数。
var value; var A = function(callback) { setTimeout(function() { value = 10; callback(); }, 200); }; var B = function() { console.log(value); }; A(function() { B(); });这样确实有用,但想象一下加入我们需要运行5个或更多方法时将会发生什么。一直传递回调函数将会导致混乱和非常不雅观的代码。
var queue = function(funcs) { // 接下来请看,董卿??? }接着,我们要做的是通过传递A和B来运行该函数 - queue([A, B])。我们需要取得第一个函数并执行它。
var queue = function(funcs) { var f = funcs.shift(); f(); }如果执行这段代码,您将看到一个 TypeError: undefined is not a function。这是因为 A函数没收到回调参数但却试图运行它。让我们换一种调用方法。
var queue = function(funcs) { var next = function() { // ... }; var f = funcs.shift(); f(next); };在 A执行完后会调用 next 方法。将下一步操作放在 next 函数列表中是个很好的做法。我们可以将代码归拢在一起,而且我们能够传递整个数组(即便数组中有很多函数等待执行)。
var queue = function(funcs) { var next = function() { var f = funcs.shift(); f(next); }; next(); };到了这一步,我们基本上达到了我们的目标。即函数A 执行后,接着会调用 B,打印出变量的正确值。这里的关键是 shift 方法的使用。它删除数组的第一个元素并返回该元素。一步一步执行下去, funcs数组就会变成 empty(空的)。所以,这可能会导致另一个错误。为了证明这一观点,让我们假设我们仍然需要运行这两个功能,但我们不知道他们的顺序。在这种情况下,两个函数都应该接受回调参数(callback )并执行它。
var A = function(callback) { setTimeout(function() { value = 10; callback(); }, 200); }; var B = function(callback) { console.log(value); callback(); };当然,我们会得到 TypeError: undefined is not a function.
var queue = function(funcs) { (function next() { if(funcs.length > 0) { var f = funcs.shift(); f(next); } })(); };我们所做的就是定义 next 函数并调用它。这种写法减少了一点代码。
var queue = function(funcs, scope) { (function next() { if(funcs.length > 0) { var f = funcs.shift(); f.apply(scope, [next]); } })(); };我们为这个tiny 类库增加了一个参数。接着我们使用 apply 函数,而不是直接调用 f(next),来设置scope 并将参数 next 传递进去。同样的功能,但漂亮多了。
var queue = function(funcs, scope) { (function next() { if(funcs.length > 0) { var f = funcs.shift(); f.apply(scope, [next].concat(Array.prototype.slice.call(arguments, 0))); } })(); };下面是测试的代码:
// 测试代码 var obj = { value: null }; queue([ function(callback) { var self = this; setTimeout(function() { self.value = 10; callback(20); }, 200); }, function(callback, add) { console.log(this.value + add); callback(); }, function() { console.log(obj.value); } ], obj);执行后的输出为:
30 10为了代码的可读性和美观,我们将部分相关的代码移到一行内:
var queue = function(funcs, scope) { (function next() { if(funcs.length > 0) { funcs.shift().apply(scope || {}, [next].concat(Array.prototype.slice.call(arguments, 0))); } })(); };你可以 点击这里查看并调试相关代码 ,完整的测试代码如下:
var queue = function(funcs, scope) { (function next() { if(funcs.length > 0) { funcs.shift().apply(scope || {}, [next].concat(Array.prototype.slice.call(arguments, 0))); } })(); }; var obj = { value: null }; queue([ function(callback) { var self = this; setTimeout(function() { self.value = 10; callback(20); }, 200); }, function(callback, add) { console.log(this.value + add); callback(); }, function() { console.log(obj.value); } ], obj);
原文:http://blog.csdn.net/renfufei/article/details/19428719