Async、Await 从源码层面解析其工作原理
发布网友
发布时间:2024-10-01 11:02
我来回答
共1个回答
热心网友
时间:2024-10-21 03:49
深入理解 Async 和 Await 的工作原理,往往需要从源码层面进行剖析。使用 Babel 进行转换后,可以清晰地发现 Async 和 Await 实际上借助了 switch-case 和 promise,实现对流程的控制。以一个使用 Async 和 Await 的函数为例,我们仅关注核心部分代码。
经过 Babel 转换后的 name 函数,可以被拆分为三个主要部分:await 部分、return 部分以及 async 流程控制的结束部分(即 case "end")。这个拆分使得流程控制变得更为直观。在流程控制中,每一步执行后,都会等待合适的时机进入下一次执行。
这个“合适的时机”并非由 Async 内部决定,而是由执行的内容决定。例如,在发送异步请求后,只有在请求返回后才会进入下一个 case。
为了实现流程控制,需要借助 regenerator-runtime 这个 generator、Async 函数的运行时。它负责将 name 函数进行包装,并添加流程控制所需的信息。如 _context,以及用于流程控制的关键 helper,如 _asyncToGenerator 和 asyncGeneratorStep。通过这些辅助工具,再在 regenerator-runtime 的基础上进行一层包装,最终得到一个可以执行的函数。这个函数实际执行时,会调用封装后的函数。
在封装后的函数中,async1、async2 等实际上是在执行最终的封装函数内部的调用。这里的第三步是 Async 函数的核心机制。在 Promise.resolve(value).then(_next) 中,value 是每个分段最后的 case 返回的值。如果 value 是一个 Promise,那么在它 resolved 后,会将其.then添加到微任务队列。如果 value 不是一个 Promise,则直接添加,因为.then是一个微任务,当执行到它时,会调用_next,从而开始执行下一个 case。
经过转换后的代码展示了封装后的函数内容,最终执行的是封装后的函数,因此说 async1、async2 执行实际上是执行封装后的函数。在封装后的函数内部,会调用 async1、async2。