概述
- Javascript是一门单线程的脚本语言
- 时间循环(EventLoop)是JavaScript的运行机制
首先我们先看一下以下代码
setTimeout(function() {
console.log('s1')
}, 0)
setTimeout(function() {
console.log('s2')
Promise.resolve().then(() => {
console.log('s2 - promise')
})
}, 0)
new Promise(function executor(resolve) {
console.log('p1')
resolve()
console.log('p2')
}).then(function() {
console.log('promise then')
})
console.log('end')
在公布结果之前先分析一下以上代码的知识点有哪些?
1.宏任务 2.微任务3.事件循环
事件循环(EventLoop)
主线程从”
任务队列
“中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。
- JS程序进入JS引擎线程,函数入栈,遇到同步代码就顺序执行执行,遇到异步代码时,把异步代码任务抛给WebAPIs执行,然后继续执行接下来的同步代码,直到栈为空。
- WebAPIs执行异步任务,当执行完一个异步任务就将其对应的回调函数放入任务队列(Callback Queue)中等待。(WebAPIs是由C++实现的浏览器创建的线程,处理Dom事件,http请求,定时器任务等异步任务)
- 当执行调用栈(Call Stack)为空时,从回调队列(Callback Queue)中取出对队首的任务放入函数栈中执行,消费完出栈。
- 事件循环机制不断的循环上面步骤,直到队列为空。
任务队列
- JavaScript有一个基于事件循环的并发模型,事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。
宏任务
宏任务是JavaScript中最原始的异步任务,包括
setTimeout、setInterVal、AJAX
等,在代码执行环境中按照同步代 码的顺序,逐个进入工作线程挂起,再按照异步任务到达的时间节点,逐个进入异步任务队列,最终按照队列中的 顺序进入函数执行栈进行执行。
微任务
微任务是随着ECMA标准升级提出的新的异步任务,微任务在异步任务队列的基础上增加了【微任务】的概念,每 一个宏任务执行前,程序会先检测中是否有当次事件循环未执行的微任务,优先清空本次的微任务后,再执行下一 个宏任务,每一个宏任务内部可注册当次任务的微任务队列,再下一个宏任务执行前运行,微任务也是按照进入队 列的顺序执行的。
Promise.then catch finally
就为微任务
- 上边的代码执行结果为
- p1
- p2
- end
- promise then
- s1
- s2
- s2 – promise
分析
-
从上往下来看
setTimeOut
为宏任务 放到栈里面不执行 ,
new Promise
为同步代码块先执行
then
为微任务不执行
console.log(‘p1’)
console.log(‘p2’)
console.log(‘end’)
- 同步代码执行完成后我们发现既有微任务和宏任务,微任务和宏任务同时存在则优选执行微任务。
console.log(‘promise then’)
-
执行宏任务每一个宏任务是单独的,如果宏任务中既有宏任务又有微任务也有同步代码,我们需要按照
同步代码>微任务>宏任务
的执行顺序
console.log(‘s1’)
console.log(‘s2’)
console.log(‘s2 – promise’)
参考链接:https://www.ruanyifeng.com/blog/2014/10/event-loop.html