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))来保存一个事件循环迭代是一个有争议的选择。通常情况下,对正在迭代的集合进行变异并不是最好的方法。但我并不是坚持,这取决于每个人如何编写他们的代码。