这两者之间有什么区别吗:

const [result1, result2] = await Promise.all([task1(), task2()]);

and

const t1 = task1();
const t2 = task2();

const result1 = await t1;
const result2 = await t2;

and

const [t1, t2] = [task1(), task2()];
const [result1, result2] = [await t1, await t2];

当前回答

如果等待Promise.all([task1(), task2()]);“task1()”和“task2()”将并行运行,并等待两个promise都完成(解决或拒绝)。而在

const result1 = await t1;
const result2 = await t2;

T2将只在t1完成执行(已被解析或拒绝)后运行。t1和t2都不是平行的。

其他回答

以防万一,除了已经很棒的答案之外:

const rejectAt = 3; // No worries. "3" is purely awesome, too! Just for the tiny example! document.body.innerHTML = ''; o("// With 'Promise.all()':"); let a = Promise.all([ test(1), test(2), test(3), test(4), test(5), ]).then(v => { o(`+ Look! We got all: ${v}`); }).catch(e => { o(`x Oh! Got rejected with '${e}'`); }).finally(() => { o("\n// With 'await':"); async function test2() { try { r = []; r.push(await test(1)); r.push(await test(2)); r.push(await test(3)); r.push(await test(4)); r.push(await test(5)); o(`+ Look! We got all: ${r.join(',')} // Twice as happy! ^^`); } catch (e) { o(`x Ah! Got rejected with '${e}'`); } } test2(); }); function test(v) { if (v === rejectAt) { o(`- Test ${v} (reject)`); return new Promise((undefined, reject) => reject(v)); } o(`- Test ${v} (resolve)`); return new Promise((resolve, undefined) => resolve(v)); } // ---------------------------------------- // Output function o(value) { document.write(`${value}\n`); } body { white-space: pre; font-family: 'monospace'; }

可能的结果:

// With 'Promise.all()':
- Test 1 (resolve)
- Test 2 (resolve)
- Test 3 (reject)
- Test 4 (resolve)
- Test 5 (resolve)
x Oh! Got rejected with '3'

// With 'await':
- Test 1 (resolve)
- Test 2 (resolve)
- Test 3 (reject)
x Ah! Got rejected with '3'

通常,使用Promise.all()以“异步”方式并行运行请求。使用await可以并行运行或被“同步”阻塞。

下面的Test1和test2函数显示await如何运行async或sync。

test3显示的Promise.all()是异步的。

Jsfiddle计时结果-打开浏览器控制台查看测试结果

同步行为。不并行运行,耗时~1800ms:

const test1 = async () => {
  const delay1 = await Promise.delay(600); //runs 1st
  const delay2 = await Promise.delay(600); //waits 600 for delay1 to run
  const delay3 = await Promise.delay(600); //waits 600 more for delay2 to run
};

异步行为。并行运行,约600ms:

const test2 = async () => {
  const delay1 = Promise.delay(600);
  const delay2 = Promise.delay(600);
  const delay3 = Promise.delay(600);
  const data1 = await delay1;
  const data2 = await delay2;
  const data3 = await delay3; //runs all delays simultaneously
}

异步行为。并行运行,耗时约600ms:

const test3 = async () => {
  await Promise.all([
  Promise.delay(600), 
  Promise.delay(600), 
  Promise.delay(600)]); //runs all delays simultaneously
};

TLDR;如果你正在使用Promise.all(),它也会“快速失败”——在任何包含的函数第一次失败时停止运行。

注意: 这个答案只涵盖了await in series和Promise.all之间的时间差异。一定要阅读@mikep的全面回答,它还涵盖了错误处理中更重要的差异。


为了回答这个问题,我将使用一些示例方法:

Res (ms)是一个接受毫秒整数的函数,并返回一个承诺,该承诺在该毫秒后解析。 Rej (ms)是一个函数,它接受一个毫秒的整数,并返回一个承诺,该承诺在这个毫秒之后被拒绝。

调用res启动定时器。使用的承诺。所有等待少量延迟的问题将在所有延迟结束后解决,但请记住它们是同时执行的:

示例# 1

const data = await Promise.all([res(3000), res(2000), res(1000)])
//                              ^^^^^^^^^  ^^^^^^^^^  ^^^^^^^^^
//                               delay 1    delay 2    delay 3
//
// ms ------1---------2---------3
// =============================O delay 1
// ===================O           delay 2
// =========O                     delay 3
//
// =============================O Promise.all

异步函数示例(){ const start = Date.now() 令I = 0 函数res(n) { Const id = ++i 返回新的承诺((resolve, reject) => { setTimeout(() => { 解决() console.log(' res #${id}在${n}毫秒后调用',Date.now() - start) }, n) }) } const data = await Promise.all([res(3000), res(2000), res(1000)]) console.log('的承诺。all finished ', Date.now() - start) } 例()

这意味着承诺。3秒后,所有问题将与来自内部承诺的数据一起解决。

但是,承诺。所有这些都有“快速失败”的行为:

例# 2

const data = await Promise.all([res(3000), res(2000), rej(1000)])
//                              ^^^^^^^^^  ^^^^^^^^^  ^^^^^^^^^
//                               delay 1    delay 2    delay 3
//
// ms ------1---------2---------3
// =============================O delay 1
// ===================O           delay 2
// =========X                     delay 3
//
// =========X                     Promise.all

async function example() { const start = Date.now() let i = 0 function res(n) { const id = ++i return new Promise((resolve, reject) => { setTimeout(() => { resolve() console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start) }, n) }) } function rej(n) { const id = ++i return new Promise((resolve, reject) => { setTimeout(() => { reject() console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start) }, n) }) } try { const data = await Promise.all([res(3000), res(2000), rej(1000)]) } catch (error) { console.log(`Promise.all finished`, Date.now() - start) } } example()

如果你使用async-await来代替,你将不得不等待每个promise按顺序解析,这可能不那么有效:

示例# 3

const delay1 = res(3000)
const delay2 = res(2000)
const delay3 = rej(1000)

const data1 = await delay1
const data2 = await delay2
const data3 = await delay3

// ms ------1---------2---------3
// =============================O delay 1
// ===================O           delay 2
// =========X                     delay 3
//
// =============================X await

async function example() { const start = Date.now() let i = 0 function res(n) { const id = ++i return new Promise((resolve, reject) => { setTimeout(() => { resolve() console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start) }, n) }) } function rej(n) { const id = ++i return new Promise((resolve, reject) => { setTimeout(() => { reject() console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start) }, n) }) } try { const delay1 = res(3000) const delay2 = res(2000) const delay3 = rej(1000) const data1 = await delay1 const data2 = await delay2 const data3 = await delay3 } catch (error) { console.log(`await finished`, Date.now() - start) } } example()

你可以自己查一下。

在这个小提琴中,我运行了一个测试来演示await的阻塞性质,而不是Promise。所有这些都将开始所有的承诺,当一个在等待的时候,它将与其他的一起继续。

如果等待Promise.all([task1(), task2()]);“task1()”和“task2()”将并行运行,并等待两个promise都完成(解决或拒绝)。而在

const result1 = await t1;
const result2 = await t2;

T2将只在t1完成执行(已被解析或拒绝)后运行。t1和t2都不是平行的。