Очень проницательно, jQuery.when
это то, что вам нужно. Он принимает либо промис, либо обычный non-thenable и возвращает промис сверх этого значения. Однако, поскольку у вас есть функции, а не значения, это на самом деле не требуется, поскольку в любом случае это поведение .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`
}
(скрипка)
В качестве альтернативы вы можете уменьшить;
var res = queue.reduce(function(prev,cur){ // chain to res later to hook on done
return prev.then(cur);
}, $.Deferred().resolve());
Если у вас есть больше кода, выполняющего действия ниже этого, поскольку функции в очереди могут выполняться синхронно или асинхронно (или несколько синхронно, а затем мы попадаем в асинхронную), чтобы избежать хаоса, вы можете обеспечить, чтобы функции всегда выполнялись асинхронно. Вы можете легко сделать это, обернув resolve
в начальном Deferred
в setTimeout
:
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);
Теперь процесс не запустится, пока не истечет время ожидания, и любой код, следующий за этим, обязательно запустится до того, как запустится первая функция из очереди. На мой взгляд, это несовместимо с семантикой обещаний jQuery (поскольку они несовместимы в отношении синхронизации и асинхронности). обратные вызовы), но вам может понадобиться согласованность.
Если вам нужно знать, когда процесс завершится, просто используйте обработчик .then
для res
:
res.then(function() {
// All functions have now completed
});
Для таких ситуаций вот простая функция-оболочка, которая делает и то, и другое:
function clearQueue(q) {
var p = $.Deferred();
setTimeout(p.resolve.bind(p), 0);
return q.reduce(function(prev,cur){
return prev.then(cur);
}, p);
}
Пример использования (fiddle):
clearQueue(queue).then(function() {
console.log("All done");
});
console.log("This runs before any queued function starts");
person
Benjamin Gruenbaum
schedule
24.07.2014