执行上下文:为什么此javascript代码的行为如下所示?

时间:2019-09-16 12:37:06

标签: javascript asynchronous

我已经开始学习JavaScript中的异步编程。 请看下面的代码:

const myPromise = () => Promise.resolve('I have resolved');

function firstFunction() {
  myPromise().then(res => console.log(res));
  console.log('firstFunction');
}

async function secondFunction() {
  console.log(await myPromise());
  console.log('secondFunction');
}

firstFunction()
secondFunction();

此代码将产生以下输出:

  • firstFunction
  • 我解决了
  • 我解决了
  • secondFunction

我对输出感到满意,并且我想我理解为什么会这样:

  • FirstFunction()转到调用堆栈
  • 承诺将在事件循环中被搁置
  • console.log('firstFunction')运行并打印出来(firstFunction)
  • 现在调用堆栈为空,因此已解决的承诺打印(我已解决)
  • 下一个SecondFunction()转到调用堆栈
  • 因为我们正在使用异步等待,所以代码将等待myPromise()
  • 然后打印(我已解决)
  • 最后它将打印(secondFunction)

当我将上面的代码更改为以下代码时:

const myPromise = () => Promise.resolve('I have resolved');

function sayHi() {
  console.log('hi');
}

function firstFunction() {
  myPromise().then(res => console.log(res));
  console.log('firstFunction');
}

async function secondFunction() {
  console.log(await myPromise());
  console.log('secondFunction');
}

firstFunction()
secondFunction();
sayHi();

我希望代码输出以下内容:

  • firstFunction
  • 我解决了
  • 我解决了
  • secondFunction

但是代码输出:

  • firstFunction
  • 我解决了
  • 我解决了
  • secondFunction

能否请您向我解释此代码行为?

3 个答案:

答案 0 :(得分:1)

为了使消息队列执行存储的消息(来自异步函数),调用堆栈需要为空

您可以查看关于article的事件循环,以说明这种行为。

在第二种情况下,在执行消息队列内的消息之前,调用栈具有3个需要执行并从中删除的函数,因此必须在异步调用之前打印hi

secondFunction之所以最后执行是因为它在异步函数中并且在它之前有一个等待。

答案 1 :(得分:0)

想象一下以下数字:

1-firstFunction()

2-secondFunction();

3-sayHi();

Hi在列表中排第二,因为到达第3位比解决承诺更快。由于编号1中的console.log()不在承诺中,因此它会立即执行,并依次在hi消息之前发生。

1、2和3都已执行,但是由于1和2中的promise值要花x毫秒更长的时间才能解决,因此在任何基于promise的控制台日志中都将打印Hi。

答案 2 :(得分:0)

带有注释的

function firstFunction() {
  myPromise().then(res => console.log(res)); // this console.log will be called 
                                             //after myPromise() is _resolved_
  console.log('firstFunction');              // this console.log will be called 
                                             // after function myPromise() is _called_
}

async function secondFunction() {
  console.log(await myPromise()); // again, not gonna console.log until myPromise()
                                  // is resolved...
  console.log('secondFunction');  // and any subsequent line isn't going to be executed
                                  // until `await` is complete
}