vlambda博客
学习文章列表

深入理解JS异步编程

关注小海豚,我们一起快乐滴成长


杨新



多飞前端工程师。喜爱魔幻题材的美剧,魔兽、权游的忠实拥趸,信奉奥卡姆剃刀定律,大道至简。擅长JS、CSS、C语言。他分享的课题是《深入理解JS异步编程》。


在前端开发中,JS是主要语言,而在JS中异步又是一个无处不在的存在,它在日常的前台业务需求中扮演着重要的角色。理解JS异步对于日常编码和完成一系列相对复杂的业务需求大有裨益。今天,小海豚就和你一起来探讨JS的异步。


什么是异步


首先,我们先了解一下,什么是异步?以“烧水”为例。


深入理解JS异步编程


很久之前,人们只能通过水的沸腾程度来判断水是否烧开,期间需要寸步不离地在火炉旁边看守,只能做这一件事。如今,我们用热水壶烧水,当水烧开后,热水壶会有提醒,期间我们可以去做一些其他事情。

我们可以说传统烧水是同步,现代热水壶烧水是异步。


事件循环Event Loop


事件循环中的异步队列有两种:macro(宏任务)队列和 micro(微任务)队列。

一个完整的Event Loop过程,可以概括为以下阶段:


深入理解JS异步编程


初始状态:调用栈空。micro 队列空,macro 队列里有且只有一个 script 脚本(整体代码)。

全局上下文(script 标签)被推入调用栈,同步代码执行。执行的过程通过对一些接口的调用,产生新的 macro-task 与 micro-task,分别被推入各自的任务队列。同步代码执行完毕,script 脚本被移出 macro 队列,这个过程本质上就是队列的 macro-task 的执行和出队的过程。

上一步出队的是macro-task,这一步处理micro-task。需要注意的是:当 macro-task 出队时,任务是一个一个执行的;而 micro-task 出队时,任务是一队一队执行的。因此,处理 micro 队列这一步,会逐个执行队列中的任务并把它出队,直到队列被清空。


JS异步API


01

回调函数


回调是一个函数的调用过程。函数a有一个参数,这个参数叫函数b,当函数a执行结束后执行函数b的过程,就叫做回调。


02

Promise

Promise对象是一个构造函数,用来生成Promise实例。

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,两个参数由 JavaScript 引擎提供。

深入理解JS异步编程

resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。

reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

深入理解JS异步编程

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。


03

Generator


Generator 函数有多种理解角度。

语法上,Generator 函数是一个状态机,封装了多个内部状态。

深入理解JS异步编程

执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

形式上,Generator 函数是一个普通函数,但是有两个特征。一是function关键字与函数名之间有一个星号;二是函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。



文字/小海豚

图片/小海豚

排版/小海豚



多飞学院

dooffe


点小花花,让他们知道你“在看”