以下两者之间有什么区别吗

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

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

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

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

推荐答案

Note:

这个答案只涵盖了串联awaitPromise.all之间的时序差异.一定要读到@mikep's comprehensive answer that also covers the more important differences in error handling.


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

  • res(ms)是一个以毫秒为整数的函数,并返回在该整数毫秒之后解析的promise .
  • rej(ms)是一个以毫秒为整数的函数,它返回一个promise ,但在那许多毫秒之后拒绝.

拨打res会启动计时器.使用Promise.all等待少量延迟将在所有延迟结束后解决,但请记住它们是同时执行的:

Example #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

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)
    })
  }

  const data = await Promise.all([res(3000), res(2000), res(1000)])
  console.log(`Promise.all finished`, Date.now() - start)
}

example()

这意味着Promise.all将在3秒后与来自内部promise 的数据进行解析.

但是,Promise.all has a "fail fast" behavior:

Example #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 按顺序解析,这可能效率较低:

Example #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()

Javascript相关问答推荐

具有相同参数的JS类

拖放仅通过 Select 上传

Rehype将hashtag呈现为URL

在观察框架中搜索CSV数据

单击ImageListItemBar的IconButton后,在Material—UI对话框中显示图像

构造HTML表单以使用表单数据创建对象数组

在拖放时阻止文件打开

如何从html元素创建树 struct ?

从包含数百行的表中获取更改后的值(以表单形式发送到后端)的正确方法是什么?

使用原型判断对象是否为类的实例

如何在ASP.NET项目中使用Google Chart API JavaScript将二次轴线值格式化为百分比

使用getBorbingClientRect()更改绝对元素位置

覆盖加载器页面避免对页面上的元素进行操作

是否可以在Photoshop CC中zoom 路径项?

Chrome上的印度时区名S有问题吗?

在对象的嵌套数组中添加两个属性

在HTML中使用meta标记来指定定制元数据以用于使用JavaScript进行检索是不是一个坏主意?

我想为我的Reaction项目在画布上加载图像/视频,图像正在工作,但视频没有

:host::ng-Deep不将样式应用于material 复选框

已在EventListener中更新/更改异步的React.js状态对象,但不会导致组件重新呈现