首页 > 解决方案 > 一行中的多个等待(嵌套异步调用)

问题描述

我找不到任何关于await一行中的多个 's 意味着什么或应该如何处理它们的好信息。所以我创建了以下测试代码(在 Node 中执行):

async function resolveAfterNSeconds(n, value) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(value);
    }, n*1000);
  });
};

async function test(which) {
  const start = new Date().getTime();
  let result;
  switch (which) {
    case 1:
      result = await resolveAfterNSeconds(10, await resolveAfterNSeconds(2, 'done'));
      break;
    case 2:
      result = await resolveAfterNSeconds(2, await resolveAfterNSeconds(10, 'done'));
      break;
    case 3:
      result = await resolveAfterNSeconds(10, resolveAfterNSeconds(2, 'done'));
      break;
    case 4:
      result = await resolveAfterNSeconds(2, resolveAfterNSeconds(10, 'done'));
      break;
    case 5:
      result = resolveAfterNSeconds(10, await resolveAfterNSeconds(2, 'done'));
      break;
    case 6:
      result = resolveAfterNSeconds(2, await resolveAfterNSeconds(10, 'done'));
      break;
  }
  const end = new Date().getTime();
  console.log([which, result, (new Date().getTime()-start)/1000]);
}

test(1); // [1, 'done', 12], as expected
test(2); // [2, 'done', 12], as expected
test(3); // [3, 'done', 10], as expected (kind of)
test(4); // [4, 'done', 10], but expected: [4, Promise, 2]
test(5); // [5, Promise, 2], as expected
test(6); // [6, Promise, 10], as expected

我想我确实理解为什么在案例 3'done'中返回而不是相应的Promise- 到那时 2s 超时已经完成(我是对的吗?)。

但是,我不明白案例 4:似乎一await开始的那个也与 inner 有某种关系Promise,因为否则,这不应该在 2s 之后Promise返回(而不是)吗?'done'

但是,如果外部await实际上也确实与内部相关Promise,这是否意味着案例 1 和 2 是无意义的,并且应该始终用案例 3 和 4(分别)替换,以便两个或await更多在一条线上永远有用吗?

标签: javascriptpromiseasync-await

解决方案


我想我确实理解为什么在第 3 种情况下,返回“完成”而不是相应的 Promise - 到那时 2 秒超时已经完成(对吗?)。

不,它与案例 4 相同。

但是,我不明白案例 4:似乎一开始的 await 也与内部 Promise 有某种关系,因为否则,这个 Promise 不应该在 2 秒后返回(而不是“完成”)吗?

如果你用另一个 Promise (Y) 解决一个 Promise (X),那么 Promise X采用Promise Y 的状态。

但是,如果外部 await 实际上也确实与内部 Promise 相关,这是否意味着案例 1 和 2 是无意义的,应该始终替换为案例 3 和 4(分别),

不,他们有不同的行为。

如果你await是一个 promise (Y) 并使用它的解析值作为创建另一个 promise (X) 的函数的参数,那么该函数在 Y 解析之前不会开始运行。

如果您不等待它,那么它将在Y解决之前开始运行(因此包装在 Promise 中的两个操作可以并行运行)。


推荐阅读