在循环中使用 q promise 的最佳方法是什么?等待链完成,然后再迭代到下一个

Whats the best approach to use q promise in a loop? Waiting for chain to complete before iterating to next

本文关键字:等待 然后 下一个 迭代 是什么 循环 promise 方法 最佳      更新时间:2023-09-26

我有以下情况:

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 s。如果您需要使用(很棒的)Q 库,您可以通过在Promise.resolve(arg).then(fn)位置替换Q.fcall(fn, arg)或使用Q()而不是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);
}

使用 array#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)