Node.js原生Promise.all是并行还是顺序处理?
我想澄清这一点,因为文件不太清楚;
Q1: Promise.all(iterable)
是顺序还是并行处理所有的promise? 或者更具体地说,它就像运行链式承诺一样
p1.then(p2).then(p3).then(p4).then(p5)....
还是其他types的algorithm,其中所有p1
, p2
, p3
, p4
, p5
等被同时调用(并行),并且一旦所有parsing(或一个拒绝)就返回结果?
问题2:如果Promise.all
并行运行,有没有一种方便的方法来按顺序运行一个迭代器?
注意 :我不想使用Q或Bluebird,但所有原生ES6规格。
Promise.all(iterable)
执行所有的承诺?
不,承诺不能“执行”。 当他们被创build时,他们开始他们的任务 – 他们只代表结果 – 并行执行一切,甚至在将它们传递给Promise.all
之前。
Promise.all
只等待多重承诺。 它不关心它们解决的顺序,或者计算是否并行运行。
有没有一种方便的方式来运行一个迭代序列?
如果你已经有了诺言,那么Promise.all([p1, p2, p3, …])
(没有序列的概念)就不能做太多的Promise.all([p1, p2, p3, …])
。 但是如果你有一个asynchronous函数的迭代,你可以确实按顺序运行它们。 基本上你需要从中得到
[fn1, fn2, fn3, …]
至
fn1().then(fn2).then(fn3).then(…)
解决scheme是使用Array::reduce
:
iterable.reduce((p, fn) => p.then(fn), Promise.resolve())
Bergis的回答让我在正确的轨道上使用Array.reduce。
然而,为了实际上得到函数返回我的承诺执行一个又一个,我不得不添加更多的嵌套。
我真正的用例是我需要依次传输的文件数组,因为下游的限制…
这是我结束了。
getAllFiles().then( (files) => { return files.reduce((p, theFile) => { return p.then(() => { return transferFile(theFile); //function returns a promise }); }, Promise.resolve()).then(()=>{ console.log("All files transferred"); }); }).catch((error)=>{ console.log(error); });
如以前的答案所示,使用:
getAllFiles().then( (files) => { return files.reduce((p, theFile) => { return p.then(transferFile(theFile)); }, Promise.resolve()).then(()=>{ console.log("All files transferred"); }); }).catch((error)=>{ console.log(error); });
在启动另一个文件之前没有等待传输完成,并且在第一个文件传输开始之前传输“所有文件已传输”文本。
不知道我做错了什么,但想分享什么对我有用。
编辑:自从我写这篇文章,我现在明白为什么第一个版本不起作用。 那么()期望一个函数返回一个promise。 所以,你应该传入没有括号的函数名称! 现在,我的函数需要一个参数,然后我需要包装在一个匿名的function,没有任何争论!
只是为了阐述@ Bergi的答案(这是非常简洁,但棘手的理解;)
此代码将运行数组中的每个项目,并将下一个“然后链接”添加到结尾;
function eachorder(prev,order) { return prev.then(function() { return get_order(order) .then(check_order) .then(update_order); }); } orderArray.reduce(eachorder,Promise.resolve());
希望是有道理的。
在平行下
await Promise.all(items.map(async item => { await fetchItem(item) }))
按顺序
for (var i = 0; i < items.length; i++) { await fetchItem(items[i]) }
您也可以使用recursion函数按顺序处理一个迭代。 例如,给定一个数组a
来处理asynchronous函数someAsyncFunction()
:
var a = [1, 2, 3, 4, 5, 6] function someAsyncFunction(n){ return new Promise((resolve, reject) =>{ setTimeout(() => { console.log("someAsyncFunction: ", n) resolve(n) }, Math.random() * 1500) }) }
您可以按顺序运行每个arrays:
function sequential(arr, index=0) { if (index >= arr.length) return Promise.resolve() return someAsyncFunction(arr[index]) .then(r => { console.log("got value: ", r ) return sequential(arr, index + 1) }) } sequential(a).then(() => console.log("done"))
你可以通过for循环来完成。
asynchronous函数返回承诺
async function createClient(client) { return await Client.create(client); } let clients = [client1, client2, client3];
如果你写下面的代码,那么客户端是并行创build的
const createdClientsArray = yield Promise.all(clients.map((client) => createClient(client); ));
那么所有的客户都是并行创build的。 但如果你想创build客户端顺序,那么你应该使用for循环
const createdClientsArray = []; for(let i = 0; i < clients.length; i++) { const createdClient = yield createClient(clients[i]); createdClientsArray.push(createdClient); }
那么所有的客户端都是依次创build
快乐编码:)
我一直用来解决顺序的承诺。 我不确定这是否有帮助,但这是我一直在做的。
async function run() { for (let val of arr) { const res = await someQuery(val) console.log(val) } } run().then().catch()