学习目标:
掌握宏任务、微任务,理解之前先了解js运行机制
学习内容:
一宏任务和微任务是什么
首先需要了解一下js的运行机制,
- JS是单线程执行
”JS是单线程的”指的是JS 引擎线程。- 宿主环境
JS运行的环境。一般为浏览器或者Node。- 执行栈
是一个存储函数调用的栈结构,遵循先进后出的原则。循环事件:Event Loop中,每一次循环称为tick,每一次tick的任务如下:
- 执行栈选择最先进入队列的宏任务(一般都是script)执行其同步代码直至结束;
- 检查是否存在微任务,有则会执行至微任务队列为空;
- 如果宿主为浏览器,可能会渲染页面;
- 开始下一轮tick,执行宏任务中的异步代码(setTimeout等回调)。
ES6 规范中,microtask 称为 jobs,macrotask 称为 task
宏任务是由宿主发起的,而微任务由JavaScript自身发起。
二、宏任务、微任务有哪些?
宏任务:
1. script (可以理解为外层同步代码)
2. setTimeout/setInterval
3. UI rendering/UI事件
4. postMessage,MessageChannel
5. setImmediate,I/O(Node.js)
6.ajax,读取文件
微任务:1. Promise.then
2.process.nextTick(Node.js)
3. Object.observe(已废弃;Proxy 对象替代)
4. MutaionObserver
三、宏任务、微任务是怎么执行的
执行顺序:先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕。
案例:
process.nextTick(()=>{
console.log(7);
})
console.log(1);
setImmediate(()=>{
console.log(0);
})
setTimeout(()=>{console.log(4)},0)//到点之后会把该任务放到任务队列中去,什么时候执行:需要看运行栈中还有没有任务,运行栈执行完才可以执行
setTimeout(()=>{console.log(2)},1000)
setTimeout(()=>{console.log(3)},0)
console.log(5);
//1,5,7,3,4,0,2
运行步骤:
1.同步
2.nextTick
3.异步:(包括宏任务,微任务)
1宏任务"计时器,ajax,读取文件
2微任务:promise.then
微任务先于宏任务执行
4.setImmediate
(当前事件循环结束执行,setTimeout(()=>{console.log(4)},0)和setTimeout(()=> {console.log(3)},0) 属于一个当前事件,结束之后就执行setImmediate, 然后再执行setTimeout(()=> {console.log(2)},1000))
注意:异步执行setTimeout时,是到时间把该任务放入到任务队列里面,此时代码还没有执行,所有定时器会有误差,不一定到时间就执行
补充其他:
四.DOM的渲染任务
DOM渲染也属于宏任务,把script标签放在dom元素后面
五.任务共享内存
let i=0
// setTime属于宏任务
setTimeout(()=>{
console.log(++i);//1
},1000)
setTimeout(()=>{
console.log(++i);//2
},1000)