异步函数与Promises一起使用很奇怪

时间:2019-02-22 12:54:04

标签: javascript asynchronous promise

我试图了解异步功能的机制。我在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容器中,以及何时执行堆栈为空,它们将作为解决其承诺的结果返回。

但是:

  1. 计时器又如何? 10,为什么20会在超时后很长时间出现-解决20会在6秒后很长的时间出现在屏幕上。

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

我决心正确理解它。

1 个答案:

答案 0 :(得分:1)

也许这将有助于清除问题。异步等待只是语法糖,因此您的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一样,但是异步await的整个目的是能够像使用promise那样使用promise编写代码同步(即阻止)代码,而不会造成then回调的嵌套混乱。