我想创造什么,我认为是被称为“瀑布”。 我想顺序地处理的异步函数(jQuery的承诺)的阵列。
这里是一个人为的例子:
function doTask(taskNum){
var dfd = $.Deferred(),
time = Math.floor(Math.random()*3000);
setTimeout(function(){
console.log(taskNum);
dfd.resolve();
},time)
return dfd.promise();
}
var tasks = [1,2,3];
for (var i = 0; i < tasks.length; i++){
doTask(tasks[i]);
}
console.log("all done");
我想它要完成他们的执行顺序(数组中存在的)任务。 因此,在这个例子中,我想要它做的任务1,等待它来解决,然后做任务2等待它来解决,做任务等3和日志“全部完成”。
也许这真的是明显的,但我一直在尝试所有下午摸不着头脑。
Answer 1:
我会尝试使用$().queue
,而不是$.Deferred
这里。 添加功能到一个队列,并准备时只调用了下一个。
function doTask(taskNum, next){
var time = Math.floor(Math.random()*3000);
setTimeout(function(){
console.log(taskNum);
next();
},time)
}
function createTask(taskNum){
return function(next){
doTask(taskNum, next);
}
}
var tasks = [1,2,3];
for (var i = 0; i < tasks.length; i++){
$(document).queue('tasks', createTask(tasks[i]));
}
$(document).queue('tasks', function(){
console.log("all done");
});
$(document).dequeue('tasks');
Answer 2:
对于一个瀑布,你需要一个异步循环:
(function step(i, callback) {
if (i < tasks.length)
doTask(tasks[i]).then(function(res) {
// since sequential, you'd usually use "res" here somehow
step(i+1, callback);
});
else
callback();
})(0, function(){
console.log("all done");
});
Answer 3:
您可以创建一个解决$ .Deferred,只是添加到与每个迭代的链条:
var dfd = $.Deferred().resolve();
tasks.forEach(function(task){
dfd = dfd.then(function(){
return doTask(task);
});
});
步步下面正在发生的事情:
//begin the chain by resolving a new $.Deferred
var dfd = $.Deferred().resolve();
// use a forEach to create a closure freezing task
tasks.forEach(function(task){
// add to the $.Deferred chain with $.then() and re-assign
dfd = dfd.then(function(){
// perform async operation and return its promise
return doTask(task);
});
});
就个人而言,我觉得这比递归清洁,不是$()比较熟悉。队列(jQuery的API为$(),因为它是专为动画队列是混乱的,但也有可能使用了$ .Deferred在其他地方你码)。 它也有结果的标准传递而下的瀑布,通过解析()的异步操作,并允许$ .done属性的附加的好处。
这是一个的jsfiddle
Answer 4:
看一看在$。当和再运行deferreds方法。
瀑布是用来管返回值从一推迟到下一个串联。 它看起来会是这样 。
function doTask (taskNum) {
var dfd = $.Deferred(),
time = Math.floor(Math.random() * 3000);
console.log("running task " + taskNum);
setTimeout(function(){
console.log(taskNum + " completed");
dfd.resolve(taskNum + 1);
}, time)
return dfd.promise();
}
var tasks = [1, 2, 3];
tasks
.slice(1)
.reduce(function(chain) { return chain.then(doTask); }, doTask(tasks[0]))
.then(function() { console.log("all done"); });
注意传递给争论resolve
。 这被传递给链中的一个功能。 如果你只是想串联运行它们没有参数的管道,你可以说出来并更改减少调用.reduce(function(chain, taskNum) { return chain.then(doTask.bind(null, taskNum)); }, doTask(tasks[0]));
而在平行它看起来像这样 :
var tasks = [1,2,3].map(function(task) { return doTask(task); });
$.when.apply(null, tasks).then(function() {
console.log(arguments); // Will equal the values passed to resolve, in order of execution.
});
Answer 5:
的确是有趣的挑战。 我想出了是接受列表和可选的开始索引递归函数。
这里是对的jsfiddle一个链接 ,我已经有几个不同的列表的长度和间隔测试。
我假设你有一个返回的承诺(不是数字的列表)功能列表。 如果你有一个数字的列表,你会改变这部分
$.when(tasks[index]()).then(function(){
deferredSequentialDo(tasks, index + 1);
});
这
/* Proxy is a method that accepts the value from the list
and returns a function that utilizes said value
and returns a promise */
var deferredFunction = myFunctionProxy(tasks[index]);
$.when(tasks[index]()).then(function(){
deferredSequentialDo(tasks, index + 1);
});
我不知道有多大的功能列表可以,但要知道,浏览器会从第一deferredSequentialDo呼叫保持到资源,直到他们都完成了。
Answer 6:
参数
- 项目:参数数组
- FUNC:异步功能
- 回调:回调函数
- 更新:更新功能
简单的循环:
var syncLoop = function(items, func, callback) {
items.reduce(function(promise, item) {
return promise.then(func.bind(this, item));
}, $.Deferred().resolve()).then(callback);
};
syncLoop(items, func, callback);
跟踪进度:
var syncProgress = function(items, func, callback, update) {
var progress = 0;
items.reduce(function(promise, item) {
return promise.done(function() {
update(++progress / items.length);
return func(item);
});
}, $.Deferred().resolve()).then(callback);
};
syncProgress(items, func, callback, update);
文章来源: Asynchronous Loop of jQuery Deferreds (promises)