据我了解,在ES7 / ES2016中,在代码中放置多个await
的工做方式相似于将带有.then()
的承诺连接在一块儿,这意味着它们将一个接一个地执行而不是并行执行。 所以,例如,咱们有如下代码: node
await someCall(); await anotherCall();
我是否正确理解只有在someCall()
完成后才会调用anotherCall()
? 并行调用它们的最优雅方式是什么? chrome
我想在Node中使用它,因此也许有一个异步库解决方案? promise
编辑:我不满意此问题提供的解决方案: 减速是因为异步生成器中非并行等待promise ,由于它使用生成器,而且我询问的是更通用的用例。 浏览器
您能够在Promise.all()
上等待: 异步
await Promise.all([someCall(), anotherCall()]);
要存储结果: async
let [someResult, anotherResult] = await Promise.all([someCall(), anotherCall()]);
TL; DR ide
使用Promise.all
进行并行函数调用时,发生错误时答案行为不正确。 函数
首先,一次执行全部异步调用并获取全部Promise
对象。 其次,对Promise
对象使用await
。 这样,当您等待第一个Promise
解决其余异步调用时,仍在进行中。 整体而言,您只会等待最慢的异步调用时间。 例如: this
// Begin first call and store promise without waiting const someResult = someCall(); // Begin second call and store promise without waiting const anotherResult = anotherCall(); // Now we await for both results, whose async processes have already been started const finalResult = [await someResult, await anotherResult]; // At this point all calls have been resolved // Now when accessing someResult| anotherResult, // you will have a value instead of a promise
JSbin示例: http ://jsbin.com/xerifanima/edit?js,console spa
注意: await
调用是在同一行仍是在不一样的行上都没有关系,只要第一个await
调用发生在全部异步调用以后。 请参阅JohnnyHK的评论。
更新:这个回答有错误不一样时间处理根据@ BERGI的答案 ,如发生错误时不会抛出了错误,但全部的承诺都执行以后。 我将结果与[result1, result2] = Promise.all([async1(), async2()])
的技巧进行比较: [result1, result2] = Promise.all([async1(), async2()])
,检查如下代码片断
const correctAsync500ms = () => { return new Promise(resolve => { setTimeout(resolve, 500, 'correct500msResult'); }); }; const correctAsync100ms = () => { return new Promise(resolve => { setTimeout(resolve, 100, 'correct100msResult'); }); }; const rejectAsync100ms = () => { return new Promise((resolve, reject) => { setTimeout(reject, 100, 'reject100msError'); }); }; const asyncInArray = async (fun1, fun2) => { const label = 'test async functions in array'; try { console.time(label); const p1 = fun1(); const p2 = fun2(); const result = [await p1, await p2]; console.timeEnd(label); } catch (e) { console.error('error is', e); console.timeEnd(label); } }; const asyncInPromiseAll = async (fun1, fun2) => { const label = 'test async functions with Promise.all'; try { console.time(label); let [value1, value2] = await Promise.all([fun1(), fun2()]); console.timeEnd(label); } catch (e) { console.error('error is', e); console.timeEnd(label); } }; (async () => { console.group('async functions without error'); console.log('async functions without error: start') await asyncInArray(correctAsync500ms, correctAsync100ms); await asyncInPromiseAll(correctAsync500ms, correctAsync100ms); console.groupEnd(); console.group('async functions with error'); console.log('async functions with error: start') await asyncInArray(correctAsync500ms, rejectAsync100ms); await asyncInPromiseAll(correctAsync500ms, rejectAsync100ms); console.groupEnd(); })();
我投同意票:
await Promise.all([someCall(), anotherCall()]);
请注意调用函数的那一刻,它可能会致使意外的结果:
// Supposing anotherCall() will trigger a request to create a new User if (callFirst) { await someCall(); } else { await Promise.all([someCall(), anotherCall()]); // --> create new User here }
可是跟随老是触发建立新用户的请求
// Supposing anotherCall() will trigger a request to create a new User const someResult = someCall(); const anotherResult = anotherCall(); // ->> This always creates new User if (callFirst) { await someCall(); } else { const finalResult = [await someResult, await anotherResult] }
更新:
原始答案很难(在某些状况下是不可能)正确处理承诺拒绝。 正确的解决方案是使用Promise.all
:
const [someResult, anotherResult] = await Promise.all([someCall(), anotherCall()]);
原始答案:
只需确保在等待其中一个函数以前调用这两个函数:
// Call both functions const somePromise = someCall(); const anotherPromise = anotherCall(); // Await both promises const someResult = await somePromise; const anotherResult = await anotherPromise;
我建立了一个辅助函数waitAll,可能会使它更甜。 目前,它仅适用于nodejs , 不适用于浏览器chrome。
//const parallel = async (...items) => { const waitAll = async (...items) => { //this function does start execution the functions //the execution has been started before running this code here //instead it collects of the result of execution of the functions const temp = []; for (const item of items) { //this is not //temp.push(await item()) //it does wait for the result in series (not in parallel), but //it doesn't affect the parallel execution of those functions //because they haven started earlier temp.push(await item); } return temp; }; //the async functions are executed in parallel before passed //in the waitAll function //const finalResult = await waitAll(someResult(), anotherResult()); //const finalResult = await parallel(someResult(), anotherResult()); //or const [result1, result2] = await waitAll(someResult(), anotherResult()); //const [result1, result2] = await parallel(someResult(), anotherResult());