Javascript 如何按顺序运行一系列承诺

Javascript 如何按顺序运行一系列承诺,javascript,arrays,node.js,asynchronous,promise,Javascript,Arrays,Node.js,Asynchronous,Promise,我需要在一个项目数组上运行一些承诺,但我不知道数组的长度。我如何按顺序履行这些承诺?这是我异步执行的方式: const arrayABC = [a, b, c.....x, y, z] // length unknown const promises = arrayABC.map(function(item) { doSomething(item) } return Promise.all(promises) 我需要一个接一个地履行承诺。假设我正确理解您的设置,这似乎是最合理的方法

我需要在一个项目数组上运行一些承诺,但我不知道数组的长度。我如何按顺序履行这些承诺?这是我异步执行的方式:

const arrayABC = [a, b, c.....x, y, z] // length unknown
const promises = arrayABC.map(function(item) {
   doSomething(item)
   }
return Promise.all(promises)

我需要一个接一个地履行承诺。

假设我正确理解您的设置,这似乎是最合理的方法:

// return the promise chain from last element
return arrayABC.reduce(function (chain, item) {
  // bind item to first argument of function handle, replace `null` context as necessary
  return chain.then(doSomething.bind(null, item));
// start chain with promise of first item
}, doSomething(arrayABC.shift()));
下面的映射是异步和顺序的,而您的代码是异步和并行的

函数顺序异步映射(数组,fn){
var p=Promise.resolve();
返回Promise.all(array.map(
(项目、索引、集合)=>p=p(
()=>fn(项目、索引、集合)
)
));
}
功能延迟(超时、值){
返回新承诺(解决=>{
setTimeout(()=>解析(值),超时);
});
}
sequentialAsyncMap([1,2,3],i=>{
控制台日志(i);
返回延迟(500,2*i);
})。然后(结果=>{
控制台日志(结果);

});如果您不喜欢使用bluebird--您可以使用
.each()
按顺序运行它们。示例取自文档注释

const Promise = require('bluebird')

let queue = [];

queue.push(function() {
  return new Promise(function(resolve, reject) {
    // Some asynchronous task.
    console.log("Processing item 1...");
    setTimeout(resolve, 3000);
  });
});

queue.push(function() {
  return new Promise(function(resolve, reject) {
    // Some asynchronous task.
    console.log("Processing item 2...");
    setTimeout(resolve, 1000);
  });
});

Promise.each(queue, function(queue_item) {
  // *Now* we call the function. Since it returns a promise, the next iteration will not run until it resolves.
  return queue_item();
});

如果您需要访问所有Promises结果(就像使用Promise.all一样)-您可以执行以下操作:

Promise.series = (array, fn, thisArg) => {
    var p = Promise.resolve();
    return Promise.all(Array.from(array).map((...args) => 
        p = p
        .then(() => fn.apply(thisArg, args))
    ));
};
然后你的代码就变成了

const arrayABC = [a, b, c.....x, y, z] // length unknown
return Promise.series(promises, doSomething);
回调(在本例中为
doSomething
)将传递参数
项、索引、数组
,就像
array#map
array#forEach

thisArg
是可选的,其工作原理与将其用于
Array#map
Array#forEach
等类似

另一种
Promise.series

Promise.series = (array, fn, thisArg) => 
    Array.from(array).reduce((promise, ...args) => 
        promise
        .then(results => 
            fn.apply(thisArg, args)
            .then(result => results.concat(result))
        ), Promise.resolve([])
    );

同样的结果,但不需要承诺。所有的重复(?)这个问题在这里已经被详尽地回答了。请多搜索一点。减少在同一表达式中变异的数组看起来很难看。有人可能只是将一个伪解析承诺作为初始值传递。@zerkms这会浪费事件循环一个事件循环迭代与有争议的代码…:-这有争议吗?突变首先发生是有明确定义的。JavaScript中没有未定义的行为,我没有说这是未定义的行为。我说过,使用变异(这不是免费的——至少在当前的v8实现中,它会分配一个新数组并用旧数据填充它。因此,在操作和内存方面,您的移位是O(N))来保存一个事件循环迭代是一个有争议的选择。通常情况下,对正在迭代的集合进行变异并不是最好的方法。但我并不是坚持,这取决于每个人如何编写他们的代码。