【问题标题】:Async functions works weird with Promises异步函数与 Promises 一起工作很奇怪
【发布时间】:2019-02-22 12:54:03
【问题描述】:

我正在尝试了解异步函数的机制。我在 MDN 文档 MDN docs 上找到了一些代码,进行了一些修改,但......无法完全理解它是如何工作的。

var resolveAfter2Seconds = function() {
  console.log("starting slow promise");
  return new Promise(resolve => {
    setTimeout(function() {
      resolve(20);
      console.log("slow promise is done");
    }, 6000);
  });
};


var resolveAfter1Second = function() {
  console.log("starting fast promise");
  return new Promise(resolve => {
    setTimeout(function() {
      resolve(10);
      console.log("fast promise is done");
    }, 4000);
  });
};


var sequentialStart = async function() {
  console.log('==SEQUENTIAL START==');

  const slow = await resolveAfter2Seconds();
  const fast = await resolveAfter1Second();

  console.log(fast);
  console.log('why?');
  console.log(slow);
}


sequentialStart();

现在我知道,如果我们运行此代码,我们将立即在控制台上收到 '==SEQUENTIAL START==',然后是“开始慢速承诺”,然后我们有一个带有 setTimeout 的 Promise,它表明“慢速承诺已完成” ' 将在 6 秒后出现,并且 resolve(20) 回调将保留在 api 容器中,因为执行堆栈将为空。JS 给我们“开始快速承诺”,四秒后我们得到“快速承诺完成”,然后立即 10 , '为什么?', 20.

我不明白:后台到底发生了什么——我知道 resolve(20) 保存在 api 容器中,其余代码被执行,然后 resolve(10) 也保存在 api 容器中,当执行堆栈为空,它们作为解决 Promise 的结果返回。

但是:

  1. 计时器有什么用? 10,why,20 在超时后很久才出现 - 解决 20 在 6 秒后长时间出现在屏幕上。

  2. 订单有什么用?似乎它们(resolve20 和 resolve 10)已准备好执行并保存在内存中,直到我使用它们 - 在这种情况下在控制台中打印它们?时间出现和秩序

我非常有决心正确理解它。

【问题讨论】:

  • 我不确定我是否理解您的担忧,但是:1) 重命名函数以实际匹配它们的功能。 resolveAfter1Second() 实际上是 resolveAfter4Seconds() (另一个相同)。 2)控制台输出“10,为什么,20”是在所有承诺都解决后出现的(这是await的技巧,在承诺解决之前调用不会返回)。 3) 在您实际调用 resolve() 之前,承诺不会“解决”,这就是 setTimeout() 所做的:它在指定的时间后解决承诺。
  • 您所说的“API 容器”是什么意思,其中究竟会保留什么?这似乎是您困惑的根源。
  • 您认为这两个 await 会并行运行吗?

标签: javascript asynchronous promise


【解决方案1】:

也许这将有助于解决问题。 Async-await 只是语法糖,所以您的 sequentialStart 函数与以下内容完全相同:

var sequentialStart = function() {
  console.log('==SEQUENTIAL START==');

  resolveAfter2Seconds().then(function(slow) {

    resolveAfter1Second().then(function(fast) {

      console.log(fast);
      console.log('why?');
      console.log(slow);
    });
  });
}

我知道 resolve(20) 保存在 api 容器中并执行其余代码,然后 resolve(10) 也保存在 api 容器中,当执行堆栈为空时,它们作为解析结果返回他们的承诺

这不是使用 async-await 时发生的情况,您的代码正在执行以下特定顺序:

  1. 致电resolveAfter2Seconds()
  2. await 将其解析,然后将解析后的值赋给常量slow
  3. 致电resolveAfter1Second()
  4. await 将其解析,然后将解析后的值赋给常量fast
  5. 致电console.log(fast)然后 console.log('why?')然后 console.log(slow)

您似乎希望 Promise 能够并行解决,就像您不使用 async-await 时那样,但 async-await 的全部目的是能够编写带有 Promise 的代码,就好像它是同步(即阻塞)代码,不会创建then 回调的嵌套混乱。

【讨论】:

  • 看来我完全误解了这个问题。感谢您的解释-尤其是对于“步骤”和“语法糖”,我想我现在明白了:)
猜你喜欢
  • 2023-01-26
  • 2021-04-01
  • 2019-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
相关资源
最近更新 更多