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

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相关问答推荐

随着 Safari 中输入文本的变化,输入类型文本下方的 div 上下移动

使用javascript定位h1中每个单词的首字母

表过滤器/搜索两列

以Angular 删除 beforeunload 事件

如何让带有 p5.js 的 Pix2Pix 运行?

如何将主 js 文件中的数组用于不同的 js 文件?

使用 HTML、CSS 和 JavaScript 在页面刷新时保持选定的主题

如何解决这个错误“Uncaught TypeError: inputArgs[0].match is not a function”

根据光标位置调整 jQuery 自动完成 UI 的大小

EcmaScript 规范中 classScope 的目的是什么?

画布 putimagedata 有时不会像预期的那样绘制

正文尺寸小于视口时如何设置背景 colored颜色 ?

runtime.js:7 未捕获的错误:[RequireAuth] 不是 组件. 的所有子组件必须是

如何在保持居中的同时水平滚动到容器中的项目?

用于构建类似对象层次结构的树的递归方法无法按预期工作

ReactJS 中的私有路由条件运算符

overflow-anchor不适用于水平滚动

使用下拉菜单 HTML 创建粘性导航栏

如何将 DRACO 加载器与 GLTF 加载器一起使用?

在自定义钩子中创建一个数组是在每次状态更改时重新渲染值