Node.js原生Promise.all是并行还是顺序处理?

我想澄清这一点,因为文件不太清楚;

Q1: Promise.all(iterable)是顺序还是并行处理所有的promise? 或者更具体地说,它就像运行链式承诺一样

 p1.then(p2).then(p3).then(p4).then(p5).... 

还是其他types的algorithm,其中所有p1p2p3p4p5等被同时调用(并行),并且一旦所有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()