我有一个充满函数的对象,如下所示:
var functions = {
fun1 : function(){ ... }
fun2 : function(){ ... }
fun3 : function(){ ... }
};
对象键都在数组中引用,如下所示:
var funList = ['fun1','fun2','fun3'];
我一直在使用数组来运行所有函数:
$.each(funList, function(i,v){
functions[v].call(this, args);
});
我的问题是,我需要一些方法来延迟所有函数的运行,这样:
- 在 $.each 循环中,函数串行运行
- 一些方法可以将后续代码的运行推迟到数组/对象中的所有函数都完成之后。
我读到我应该为此使用 $.map 方法,但我很难全神贯注。
最佳答案
哇...那是一个练习——$.Deferred() 有点难以让我全神贯注,但我让它按照我想要的方式工作!我不知道这有多精简——也许其他人可以让它更有效率。
它的要点是使用 .pipe() 创建一个延迟链。
编辑:我的代码(下方)在引用键列表中容纳的对象不少于 2 个。我更新了 jsfiddle 以使用任何大小的键列表。
您可以在 JSFiddle 此处看到以下所有工作:http://jsfiddle.net/hBAsp/3/
这是我如何逐步解决它的:
从一个充满函数的对象和一组引用键(按照您希望它们处理的顺序)开始。这些函数应该期望收到一个延迟对象以在完成时解析:
var obj = { one: function(dfd){ /* do stuff */ dfd.resolve(); }, two: function(dfd){...}, three: function(dfd){...}, etc... }; var keys=['one','two','three', etc...];`
创建主要的延迟包装器,将 promise 传递给初始化函数。我们将在执行过程中将代码添加到函数中:
var mainDeferred = $.Deferred(function(mainDFD){
在该初始化函数内部,创建一个延迟数组,手动创建第一个延迟对象:
var dfds = [$.Deferred()];
接下来,使用 for 循环遍历键列表中的倒数第二个项目。我们将:
- 为我们单步执行的每个项目创建一个延迟对象
- 设置一个匿名函数,该函数将从我们的 obj 运行与键相关的函数,将其传递给它以解决我们新创建的 Deferred 对象
- 将新创建的函数通过管道传递给之前创建的 Deferred 对象(这就是我们必须手动创建第一个对象的原因)
您必须在 for 列表中使用封闭循环来解决 JavaScript 作用域问题
for (i=1; i<keys.length-1; i++){ (function(n){ dfds.push($.Deferred()); dfds[i-1].pipe(function(){ obj[keys[n]].call(this,dfds[n]); }); })(n); };
手动创建最后一个匿名函数并将其通过管道传递到我们列表中的倒数第二个延迟对象。我们手动执行此操作,因为我们想将主要的延迟对象传递给它以进行解析,以便在最后一个进程运行后立即触发整个 shebang:
dfds[keys.length-2].pipe(function(){ obj[keys[keys.length-1]].call(this,mainDFD); });
现在我们的整个管道已经构建完成,我们所要做的就是触发第一个对象并将其分配给第一个延迟以供解析:
obj[keys[0]].call(this,dfds[0]);
只需关闭我们的主要延迟初始化函数(这将在创建延迟后立即触发:
});
现在我们还可以将一个函数通过管道传递给主对象,以便在我们之前的所有元素运行之后运行:
mainDeferred.pipe(function(){ /* do other stuff */ });
关于javascript - jQuery Deferred 函数数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11833851/