什么是最好的方法使用Q承诺循环? 在迭代到下一个之前等待链完成

我有以下情况:

var ids = [120, 121, 122, 123, 124] function dummyPromise(pause) { var deferred = Q.defer(); setTimeout(function() { console.log(pause); deferred.resolve(pause); }, pause); return deferred.promise; } for(var i = 0; i < ids.length; i++) { dummyPromise(ids[i]) .then(dummyPromise) .then(dummyPromise) .then(dummyPromise) .then(dummyPromise) .done(function(){ console.log('done') }) } 

我想在迭代到下一个之前等待链完成。 什么是最好的方法来解决这个问题?

在这些例子中,我使用标准Promise 。 如果您需要使用(令人敬畏的)Q库,可以通过在Promise.resolve(arg).then(fn) Q.fcall(fn, arg)的位置replaceQ.fcall(fn, arg) Promise.resolve(arg).then(fn)或使用Q()而不是Promise.resolve()来缩短它Promise.resolve()

通过链接承诺

 var q = Promise.resolve(); for (var i = 0; i < 10; i++) { (function(item, index){ q = q.then(function() { return // do async stuff here }); })(ids[i], i); } q.then(function() { // all iterations finished }); 

用数组

 function forEachAsync(arr, fn) { var index = 0; function next() { if (index < arr.length) { var current = index++; return Promise.resolve().then(function() { return fn(arr[current], current, arr); }).then(next); } } return Promise.resolve().then(next); } ... forEachAsync(ids, function(item, idx) { ... }).then(...) 

随着迭代

 function forOfAsync(iterable, fn) { var iterator = iterable[Symbol.iterator](); function next() { var iteration = iterator.next(); if (iteration.done) { return iteration.value; } else { return Promise.resolve(iteration.value).then(fn).then(next); } } return Promise.resolve().then(next); } forOfAsync(ids, function(id) { ... }).then(...) 

async-await

 for (let id of ids) { await doSomeAsyncStuffWithId(id); } 

使用数组#reduce – 你的代码看起来像

 ids.reduce(function(prev, id) { return prev .then(function() { return dummyPromise(id) }) .then(dummyPromise) .then(dummyPromise) .then(dummyPromise) .then(dummyPromise) .then(function(){ // if you do done you can't chain console.log('done') }); }, Q(null)) .done(function() { // done here though console.log('all done'); }); 

感谢https://github.com/jprichardson/node-batchflow 。 我结束了使用这种方法:请参阅小提琴: https : //jsfiddle.net/c9fxqhs5/

  var ids = [120, 121, 122, 123, 124] function dummyPromise(pause) { var deferred = Q.defer(); setTimeout(function() { console.log(pause); deferred.resolve(pause); }, pause); return deferred.promise; } function again(i) { if (i < ids.length) { $('body').append('<p>processing: ' + i + '</p>'); dummyPromise(ids[i]) .then(dummyPromise) .then(dummyPromise) .then(dummyPromise) .then(dummyPromise) .done(function(result){ $('body').append('<p>done: ' + i + ' result=' + result + '</p>'); again(i+1) }) } else { console.log('All Done.') } } again(0)