2023-03-24 04:31:55
JavaScript 的异步编程解决方案主要包括 Callback、Promise、Generator、Async/Await,以下是对这些方案的详细介绍:
单线程异步原理JavaScript 是单线程语言,同一时间只能执行一段代码,阻塞其他代码执行。异步操作(如网络请求、IO 操作、定时函数)由浏览器多线程协作完成。例如,异步请求时,JS 执行线程发起请求,浏览器开启新线程执行请求,完成后将回调函数插入 JS 执行队列尾部等待处理。其执行流程如下:

通过定时函数实例可看出异步处理过程,先打印 1,执行 setTimeout 约定 0 秒后打印 2,再打印 3,最终执行结果为先打印 1,再打印 3,最后打印 2,说明发生了异步过程。

回调函数是最早的异步解决方案,当事件完成后执行回调函数实现异步操作。函数可作为参数传递给另一个函数,在另一个函数中调用。例如发送 Ajax 异步请求,多个请求嵌套时,回调函数会形成多级嵌套,代码呈金字塔型结构。虽然能解决异步问题,但代码难懂,调试和重构风险高。

以 mongoDB 在 node.js 中的实例为例,嵌套了六层,当多个异步事务多级依赖时,这种结构弊端明显。

Promise 是更合理强大的异步解决方案,具有以下特点:

左侧创建 promise 对象,隔 2000 秒后执行,最后返回 promise 对象。Promise 有立即执行性,创建完对象后,在已完成或已拒绝之前代码都会执行一遍。右侧为打印结果,可见创建 promise 对象被打印出来,并成功生成 promise 对象,执行 then 时,因已返回成功状态,所以一直执行成功的回调函数。

Promise 解决异步问题的特点如下:
链式调用方式中,第一个请求成功后执行下一个,若任何一个请求未成功,直接 catch 掉 error 并打印。
GeneratorGenerator 函数可实现以同步方式写异步代码,使逻辑更清晰,代码量减少。其特质如下:

首先定义 test = add(5),函数未执行,只是生成 generator 对象,函数处于暂停状态。执行.next() 时,激活暂停状态,开始执行内部代码,直到遇到第一个 yield 返回执行结果,并记住上下文,暂停,交出控制权。再次执行.next() 时,找到第二个 yield,再次记住上下文,暂停,交出控制权,依此重复。
封装异步任务时,定义 generator 对象,执行请求后交出控制权,通过 promise 判断是否继续执行。Generator 需要自动执行器配合使用,实现正常思维下的异步处理,有了自动执行器,异步请求可用同步方式写异步代码,直接将请求全部写在一起。
Async/AwaitAsync 和 await 函数是进一步演进的结果,个性特征如下:

Async 与 generator 写法类似,本质上是 generator 的语法糖。其内置执行器,具备更好的语义,更广的适用性,并且返回值是 Promise。
