async/await中的执行顺序

7

我一直在学习Promise、await和async函数。在学习Promise阶段,我偶然发现了这个:

async function async1(){
  console.log('Async 1');
  await async2();  // *
  console.log('AFter Async 1');
}

async function async2(){
  console.log('FROM async 2');
}


async1();
console.log('Synchronous'); //**

这导致:
Async 1
FROM async 2
Synchronous
AFter Async 1

代码是如何从*跳到**的?这里如何使用微任务?
1个回答

15

在你所询问的特定序列(从 ***)的执行过程中,没有微任务涉及,尽管在该序列期间会排队一个微任务(稍后运行)。

async 函数在第一个 await、未捕获的异常或 return(包括代码执行到函数结尾时的隐式返回)之前是同步的。此时,函数返回一个 promise,并从调用该函数的点继续同步执行。如果是异常或 return 或隐式返回(而不是 await),则会排队一个微任务来解决该函数的 promise(在异常时拒绝,在返回时履行)。

我已经用黄色突出显示了该代码中的同步部分:

The code from the question, with highlighting on: 1. async1 and async2's empty parameter lists, the first console.log in each, and (in async1) the call to async2() but not the await on it; 2. The two statements at the end that aren't in any function.

在你的示例中,当你在底部调用async1时,它的同步部分会运行(记录Async 1,然后调用async2,在它的同步部分期间记录FROM async 2);在运行async2并从中获得一个promise之后,async1到达await并返回自己的promise;然后同步执行继续从刚刚调用它的位置继续,记录Synchronous
在这个特定的例子中,在 *** 部分之间,为完成 async2 的 promise 排队了一个微任务。当您示例中执行同步代码的任务完成时,将从微任务队列中拾取并执行该微任务,并解决等待该微任务的 async1 的 promise;async1 的代码继续执行其日志,然后隐式返回,因此排队了一个微任务以处理该解决(在此情况下是实现),并且在 async2 微任务执行完成后,从微任务队列中获取它。但是没有任何东西等待该 promise,因此解决方案没有任何明显的影响。

一个微任务在异步函数中排队,当等待的表达式或函数返回、抛出异常或者承诺解决时,是这样吗? - undefined
@TobyHarnish - 如果我理解你的问题正确的话,基本上是的。 :-) JavaScript引擎会将“promise jobs”(在HTML规范中称为微任务)排队,以在promise被实现时调用每个promise的完成处理程序(回调函数);或者在promise被拒绝时调用每个拒绝处理程序(回调函数)(每个回调函数对应一个任务)。[1] 它还会排队一个promise job(微任务),以便在你向已经存在的promise添加一个完成处理程序时调用处理程序。 - undefined
...fulfilled, or a rejection handler to a promise that's already rejected.[2], steps 10/11 Calling an async function creates a promise to report the completion of that function's work. In the function, doing a return x (where x isn't a promise/thenable) fulfills the async function's promise (potentially queuing microtasks), and doing a throw (or... - undefined
...允许嵌套的throw未被捕获)会拒绝该承诺(可能排队微任务)。(在p是一个承诺的情况下使用return p,将会解决async函数的承诺p,这可能会履行它,拒绝它,或者保持悬而未决。解决!=履行!=解决,但人们经常混淆它们;详细信息请参阅我的博客。)使用await,函数的代码在其之后,等待回调(在承诺工作/微任务中),当/如果等待的承诺被解决。希望这有所帮助! - undefined
(与承诺无关,async 函数 -- 就像任何其他代码一样 -- 也可以直接通过在浏览器、Node.js 和 Deno 上使用 queueMicrotask 来排队一个微任务。) - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接