jQuery 延迟使用一系列函数
jQuery Deferred with an array of functions
我有一个充满函数的对象,如下所示:
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]);
-
只需要关闭我们主要的延迟初始化函数(一旦创建延迟初始化函数,这将全部触发:
});
-
现在我们还可以通过管道将函数传送到 main 对象,以便在我们之前的所有元素都运行后运行:
mainDeferred.pipe(function(){ /* do other stuff */ });
我认为您可以使用管道将回调函数作为数组进行管道传输。下面是一个示例。
var a = $.Deferred();
var b = $.Deferred();
var c = $.Deferred();
var checkA = function() {
console.log('checkA');
return a.resolve();
};
var checkB = function() {
console.log('checkB');
return b.resolve();
};
var checkC = function() {
console.log('checkC');
return c.reject();
};
checkAll = $.Deferred().resolve().promise();
checkAll = checkAll.pipe(checkA);
checkAll = checkAll.pipe(checkB);
checkAll = checkAll.pipe(checkC);
checkAll.done(function() {
return console.log('checkAll done');
}).fail(function() {
return console.log('checkAll fail');
});
输出将是
"checkA"
"checkB"
"checkC"
"checkAll fail"
如果您想查看不同的结果,可以在检查函数中将结果"解析"更改为"拒绝"。 例如:如果将检查 A 更改为拒绝。
var checkA = function() {
console.log('checkA');
return a.reject();
};
输出将是
"checkA"
"checkAll fail"
它不会去检查B和检查C,因为检查A被拒绝了。以便您可以使用数组调用函数
funList = [checkA, checkB, checkC];
for(var i=0; i<funList.length; i++){
checkAll = checkAll.pipe(funList[i]);
}
注意。必须确保回调始终返回延迟对象。
- 创建一个类似链接的按钮,并通过Javascript函数打开一个新的弹出窗口
- 将函数的上下文应用于javascript变量
- jQuery 延迟使用一系列函数
- 我可以组合成一系列管道函数,以便在多个任务中重用吗
- 如何按顺序运行一系列回调函数
- j查询如何在一系列延迟后循环函数
- 当一系列 jquery ajax 调用完成时执行一个函数(!)
- 在超时循环中执行一系列函数
- 将一系列数字作为参数传递给PHP中的JavaScript函数时出错
- 如何使函数由一系列事件触发
- 将函数调用到一系列多个指令中
- AngularJS在页面加载时运行一系列函数
- 一次一个地通过一系列函数传递ID
- 在js文件中有一系列命名函数是不好的做法吗?
- 在javascript中的一系列函数之后返回
- 精简了一系列javascript函数
- 函数测试一系列值中的值和返回值
- Ember从该控制器中的一系列函数访问控制器
- 添加无限循环函数与重置的一系列动画与jQuery
- 使用函数返回描边的一系列颜色