0
点赞
收藏
分享

微信扫一扫

javascript异步编程发展史之搞懂异步编程

hoohack 2022-03-23 阅读 93

前言

异步编程对于JavaScript语言来说非常重要,由于JavaScript是单线程语言如果没有异步编程,根本无法使用,不然就会卡死,所以理解并学会异步编程尤为重要,本文我会梳理JavaScript异步的发展史,让大家清楚了解每一种异步流程的解决方案,然后推出现在最优的异步编程方案,帮助大家彻底掌握异步在JavaScript的使用,在面试以及以后的工作中才能游刃有余。

1.基础知识掌握

要想学会异步编程,我们必须要对JavaScript写的程序运行方式足够了解,大家需要掌握的知识如下

  1. 单线程模型的理解
  2. 同步任务和异步任务,以及对应的执行顺序
  3. 任务队列和事件循环
  4. 回调函数的使用
  5. Promise的使用
  6. 生成器Generator的使用
  7. Async以及await的使用

这里我只是简单罗列了一下知识,后面讲到知识点的如果大家不是很清楚可以去查阅相关资料,末尾我会讲一些不错的文章以及视频推荐给大家
对于前面3个偏概念和理论的知识我我推荐大家阅读阮一峰老师的JavaScript标准参考教程

概链知识~阮一峰老师yyds
对于这部分阮老师讲的可能有些人理解不透彻,我简单补充一些
任务分类
宏任务包括:

setInterval
setTimeout
setTimmediate Node.Js独有
XHR callbackfn
event callbackfn
requestAnimationFrame
UI rendering

微任务包括:

Promise.then
catch finally
process.nextTick Node.Js独有
MutationObserver

执行顺序
根据任务的状态,任务的执行优先级也会有所不同,具体执行顺序如下所示:

同步任务(sync-task)
微任务(micro-task)
宏任务(macro-task)
而关于微任务和宏任务的执行,还有更详细的划分:

微任务队列中一旦有任务,将全部执行完成后再执行宏任务
宏任务队列中的任务在执行完成后,会检查微任务队列中是否有新添加的任务,如果有,那么将执行微任务队列中所有新添加的任务,如果没有则继续执行下一个宏任务
在这里插入图片描述
后面4个知识点设计内容太多,我建议大家可以阅读阮一峰老师的书籍《ES6标准入门》如果书中一些知识点不好理解,可以结合b站小野老师(小野森森)的课程去学习,最后在看书巩固一下,在此就不多赘述
那么知识铺垫已经结束,让我们开始吧!

2.JavaScript异步发展史

1.回调函数

1.我们在此就不发送类似异步请求的操作,这样会让大家对代码毫无食欲,只通过简单的模拟让大家感知
比如在此我出一个简单的题:
红灯3秒亮一次,绿灯1s亮一次,黄灯2s亮一次,请让3个灯不断交替重复亮,已知三个函数如下

在这里插入图片描述

分析:在这里我们假设这是异步请求,分别消耗了时间,让你把这个逻辑简单写出来,我们从最简单的callback方案入手,代码如下
在这里插入图片描述
这里我只是提出了非常简单的需求,可是我们就使用了三个回调函数,而且还是嵌套关系,请大家设想,假如我们是向服务器请求数据,然后拿到数据之后通过一个数据再去请求其他的数据,这样反复多次,而且其中还要夹杂一些逻辑判断,那么如果我们还使用回调函数的写法,那么代码必定会出现强耦合现象,然后后期如果数据出现变更,需求发生改变,那么当我们维护这段代码的时候,我相信大家都是痛苦的。
总结:优点:回调函数非常简单容易理解和实现,缺点不利于代码的维护和阅读,各个部分之间高度耦合等等。

3.Promise实现

可能有些人会问ES6之前还有事件监听以及发布/订阅呀,在此我就不过多叙述,因为这些知识已经非常老化,有些还需引入第三方库,已经被淘汰,大家想了解可以看看我上面那篇关于阮一峰老师的文章

3.1简单提几句关于promise

对于promise大家的理解是什么。有些人来了可能说异步,如果是这样真的体现出你很无知,promise的出现究竟相对比原来callback的方式有什么优点和不足?
其实回调函数本身并没有问题,问题是出在了多个回调函数的嵌套造成的强耦合性,而Promise就是为了解决这个问题~回调地狱才被提出来的,它不是一种语法功能,而是一种写法,允许将传统的嵌套回调函数写法转化为链式调用
我们继续对上一道题利用Promise来实现一下
在这里插入图片描述
从这里可以清楚看到完全将回调嵌套写法改为链式调用,除此之外,别无它意,
Promise最大的问题就是代码臃肿,原来的任务被Promise包装之后无论什么操作,一眼看去就是许多then的堆积,原来的语义化变得很不清楚

4.Generator函数

Generator函数可以暂停执行和恢复执行,这是能封装异步任务的根本原因,除此之外,还有2个特性可以使它可以作为异步编程的完美解决方案:函数体内的数据转换和错误处理机制
我们基于上一道题给出相应的Generator解决方案
在这里插入图片描述
由于Generator函数需要手动执行,我们可以创建一个自执行函数或者引入co这个库,来协助我们完成,相对于Promise的链式调用,Generator的写法更像是同步一样,虽然实际还是异步,但是这种代码可读性很强,而且易于维护,美中不足的是它本身是手动执行,但是自动执行才是我们实际开发中经常使用到的,于是Async,await就诞生了

5.Async,await

当你真的理解了Generator函数你对Async和await只需片刻即可掌握使用,Generator实际就是asyc函数的语法糖罢了
那么我们直接使用async函数来实现这道题吧
在这里插入图片描述
大家仔细观察是不是和上面Generator函数的代码差不多完全相似,唯一不同的就是我们把函数声明成了async异步函数,把原来的yied换成了await,然后直接调用函数就可以达到自动执行的目的,达到让异步变成同步化
这就是JavaScript异步编程的最优解决方案

5.1完善

对于上面各个不同的方案,我在此总结了最优的方案Async,await,我们虽然没有去做类似工作那种去向服务器发送请求一样获取数据,只是简单用了定时器来帮助大家清楚了解,说到这里,大家就要考虑实际工作中不是每一次发送异步请求拿到的数据都是我们想要的,如果发生错误那么我们应该在async中使用try catch将我们的异步代码包裹起来,因为当一个请求发生失败时,如果我们并没有做相应的措施那么函数就不会有响应了

结尾

对于一些复杂的异步请求,在此我没有叙述,主要是因为如果全部写完无疑是一份巨大的工作量,而且我比较菜哈哈,大家可以通过书籍或者文档来加强对于JavaScript异步编程的学习。好了感谢大家

举报

相关推荐

0 条评论