jQuery:按顺序执行函数数组(延迟和非延迟)

Rie*_*ing 4 jquery promise jquery-deferred

我使用Promises相当新,并且很难绕过jQuery deferreds.

我目前拥有的是一系列我在某一点执行的函数:

while (queue.length) {
    (queue.shift())();   
}
Run Code Online (Sandbox Code Playgroud)

这个问题是,其中一些函数是异步的,但我需要它们一个接一个地运行.

所以队列中的一些函数返回一个延迟(例如通过jQuery.ajax()),有些只是普通的函数.我想知道如何按顺序+顺序执行它们(仅在前一个函数完成时才执行下一个函数).

我想也许jQuery.when会是我想要的,但我无法弄清楚它是如何完全的,我只是来了这个:

var deferred = jQuery.Deferred();
    while (queue.length > 0) {
       deferred.done().then(queue.shift());
    }
Run Code Online (Sandbox Code Playgroud)

Ben*_*aum 29

非常精明,jQuery.when 你在找什么.它需要一个promise或一个普通的non-thenable并返回一个超过该值的promise.但是,由于这里有函数而不是值,因此.then无论如何都是这种行为.

var queue = [syncFunction, syncFunc2, returnsPromiseAsync];

var d = $.Deferred().resolve();
while (queue.length > 0) {
   d = d.then(queue.shift()); // you don't need the `.done`
}
Run Code Online (Sandbox Code Playgroud)

(小提琴)

或者,你可以减少;

var res = queue.reduce(function(prev,cur){ // chain to res later to hook on done
    return prev.then(cur);
}, $.Deferred().resolve());
Run Code Online (Sandbox Code Playgroud)

如果你有更多的代码在这之下做事,因为队列中的函数可以同步或异步运行(或者某些同步然后我们遇到异步),为了避免混乱,你可能想要确保函数总是异步运行.您可以轻松地做到这一点通过包装resolve上的最初DeferredsetTimeout:

var p = $.Deferred();
var res = queue.reduce(function(prev,cur){ // chain to res later to hook on done
    return prev.then(cur);
}, p);
setTimeout(p.resolve.bind(p), 0);
Run Code Online (Sandbox Code Playgroud)

现在,在超时发生之前,进程不会启动,并且此后的任何代码肯定会在队列中的第一个函数执行之前运行.在我看来,这与jQuery的承诺的语义不一致(因为它们在同步与异步回调方面不一致),但您可能需要一致性.

如果您需要知道该过程何时完成,只需使用.then处理程序res:

res.then(function() {
    // All functions have now completed
});
Run Code Online (Sandbox Code Playgroud)

对于这些情况,这里有一个简单的包装函数,可以同时执行这两个操作:

function clearQueue(q) {
    var p = $.Deferred();
    setTimeout(p.resolve.bind(p), 0);

    return q.reduce(function(prev,cur){ 
        return prev.then(cur);
    }, p);
}
Run Code Online (Sandbox Code Playgroud)

使用示例(小提琴):

clearQueue(queue).then(function() {
    console.log("All done");
});
console.log("This runs before any queued function starts");
Run Code Online (Sandbox Code Playgroud)

  • 现在****是美丽的.:-) (3认同)