JS 异步接口调用介绍
Js 单线程模型
JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这样设计的方案主要源于其语言特性,因为 JavaScript 是浏览器脚本语言,它可以操纵 DOM ,可以渲染动画,可以与用户进行互动,如果是多线程的话,执行顺序无法预知,而且操作以哪个线程为准也是个难题。
所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。
在 HTML5 时代,浏览器为了充分发挥 CPU 性能优势,允许 JavaScript 创建多个线程,但是即使能额外创建线程,这些子线程仍然是受到主线程控制,而且不得操作 DOM,类似于开辟一个线程来运算复杂性任务,运算好了通知主线程运算完毕,结果给你,这类似于异步的处理方式,所以本质上并没有改变 JavaScript 单线程的本质。
任务队列
所有任务可以分成两种,一种是 同步任务(synchronous),另一种是 异步任务(asynchronous) 。
同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。
所以,当在执行过程中遇到一些类似于 setTimeout 等异步操作的时候,会交给浏览器的其他模块进行处理,当到达 setTimeout 指定的延时执行的时间之后,回调函数会放入到任务队列之中。
当然,一般不同的异步任务的回调函数会放入不同的任务队列之中。等到调用栈中所有任务执行完毕之后,接着去执行任务队列之中的回调函数
JavaScript |
大家可以猜测下它的输出内容?
输出结果是1,2,set2, setTimeOut
那你可能会好奇为什么结果是这样的呢,为了讲清楚这个问题答案,我们先要搞清楚两个任务,一个是macro-task(宏任务),一个micro-task(微任务)
macro-task(宏任务)
大概包括:script(整体代码), setTimeout, setInterval, setImmediate(NodeJs), I/O, UI rendering。
micro-task(微任务)
大概包括: process.nextTick(NodeJs), Promise, 来自不同任务源的任务会进入到不同的任务队列。
执行顺序是一开始先
主循环下来,先把微队列任务执行完成,在执行宏队列的一个任务,这个宏任务完成在去执行微队列,就这样依次循环执行