深入理解JS异步编程
关注小海豚,我们一起快乐滴成长
杨新
多飞前端工程师。喜爱魔幻题材的美剧,魔兽、权游的忠实拥趸,信奉奥卡姆剃刀定律,大道至简。擅长JS、CSS、C语言。他分享的课题是《深入理解JS异步编程》。
在前端开发中,JS是主要语言,而在JS中异步又是一个无处不在的存在,它在日常的前台业务需求中扮演着重要的角色。理解JS异步对于日常编码和完成一系列相对复杂的业务需求大有裨益。今天,小海豚就和你一起来探讨JS的异步。
什么是异步
首先,我们先了解一下,什么是异步?以“烧水”为例。
很久之前,人们只能通过水的沸腾程度来判断水是否烧开,期间需要寸步不离地在火炉旁边看守,只能做这一件事。如今,我们用热水壶烧水,当水烧开后,热水壶会有提醒,期间我们可以去做一些其他事情。
我们可以说传统烧水是同步,现代热水壶烧水是异步。
事件循环Event Loop
事件循环中的异步队列有两种:macro(宏任务)队列和 micro(微任务)队列。
一个完整的Event Loop过程,可以概括为以下阶段:
初始状态:调用栈空。micro 队列空,macro 队列里有且只有一个 script 脚本(整体代码)。
全局上下文(script 标签)被推入调用栈,同步代码执行。执行的过程通过对一些接口的调用,产生新的 macro-task 与 micro-task,分别被推入各自的任务队列。同步代码执行完毕,script 脚本被移出 macro 队列,这个过程本质上就是队列的 macro-task 的执行和出队的过程。
上一步出队的是macro-task,这一步处理micro-task。需要注意的是:当 macro-task 出队时,任务是一个一个执行的;而 micro-task 出队时,任务是一队一队执行的。因此,处理 micro 队列这一步,会逐个执行队列中的任务并把它出队,直到队列被清空。
JS异步API
回调函数
回调是一个函数的调用过程。函数a有一个参数,这个参数叫函数b,当函数a执行结束后执行函数b的过程,就叫做回调。
02
Promise
Promise对象是一个构造函数,用来生成Promise实例。
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,两个参数由 JavaScript 引擎提供。
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。
reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。
03
Generator
Generator 函数有多种理解角度。
语法上,Generator 函数是一个状态机,封装了多个内部状态。
执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
形式上,Generator 函数是一个普通函数,但是有两个特征。一是function关键字与函数名之间有一个星号;二是函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
文字/小海豚
图片/小海豚
排版/小海豚
多飞学院
dooffe
点小花花,让他们知道你“在看”我