目录
一、前言
二、宏任务和微任务有哪些?
三、执行顺序
1、事件循环
事件循环的六个阶段
2、题目练习:
练习一
练习二
3、宏任务之间的执行顺序
4、微任务之间的执行顺序
process.nextTick()
5、vue中的nextTick
js任务分为同步任务和异步任务,异步任务又分为宏任务和微任务,其中异步任务属于耗时的任务。
宏任务:整体代码script、setTimeout、setInterval、setImmediate、i/o操作(输入输出,比如读取文件操作、网络请求)、ui render(dom渲染,即更改代码重新渲染dom的过程)、异步ajax等
微任务:Promise(then、catch、finally)、async/await、process.nextTick、Object.observe(⽤来实时监测js中对象的变化)、 MutationObserver(监听DOM树的变化)
js代码在执行的时候,会先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后,再将异步宏任务从队列中调入主线程执行,一直循环至所有的任务执行完毕(完成一次事件循环EventLoop)。
注意:
每个异步宏任务执行完之后,都会检查是否存在待执行的微任务;如果有,则执行完所有的微任务之后,再继续执行下一个宏任务。
一次事件循环只能处理一个宏任务,一次事件循环可以将所有的微任务处理完毕。
setTimeout(function () {
console.log('1');
})
new Promise(function (resolve) {
console.log('2');
resolve();
}).then(function () {
console.log('3');
})
console.log('4');
//打印顺序 2 4 3 1
分析:
1、遇到setTimeout,异步宏任务将其放到宏任务列表中,命名为time1;
console.log(1);
setTimeout(function () {
console.log(2);
let promise = new Promise(function (resolve, reject) {
console.log(3);
resolve();
}).then(function () {
console.log(4);
});
}, 1000);
setTimeout(function () {
console.log(5);
let promise = new Promise(function (resolve, reject) {
console.log(6);
resolve();
}).then(function () {
console.log(7);
});
}, 0);
let promise = new Promise(function (resolve, reject) {
console.log(8);
resolve()
}).then(function () {
console.log(9);
}).then(function () {
console.log(10)
});
console.log(11);
//执行顺序:1 8 11 9 10 5 6 7 2 3 4
分析:
宏任务有setTimeout、setInterval、setImmediate、i/o操作、异步的ajax,它们之间的执行也是有先后顺序,它们之间的执行顺序是:
setImmediate --> setTimeout --> setInterval --> i/o操作 --> 异步ajax
例子:
let axios = require('axios');
let fs = require('fs');
console.log('begin');
fs.readFile('1.txt',(err,data)=>{
console.log('fs');
});
axios.get('https://api.muxiaoguo.cn/api/xiaohua?api_key=fd3270a0a9833e20').then(res=>{
console.log('axios');
});
setTimeout(()=>{
console.log('setTimeout')
},0);
setImmediate(()=>{
console.log('setImmediate');
});
(async function (){
console.log('async')
})();
console.log('end');
//执行顺序:begin async end setTimeout setImmediate fs axios
setImmediate没有时间参数,它与延迟 0 毫秒的 setTimeout() 回调⾮常相似。所以当setTimeout延迟时间也是0毫秒时,谁在前面就先执行谁。此外如果setTimeout延迟时间不是0毫秒,它的执行顺序会在 i/o 操作之后。
微任务有Promise(then、catch、finally)、process.nextTick等,它们之间执行的先后顺序是:
process.nextTick --> Promise
例子:
console.log('begin');
Promise.resolve().then(()=>{
console.log('promise');
})
process.nextTick(()=>{
console.log('nextTick');
});
console.log('end');
//执行顺序:begin end nextTick promise
process表示进程,它是一个对象,对象里面有一个nextTick。
nextTick会在上一次事件循环结束,然后在下一次事件循环开始之前执行。
Vue.nextTick() 是vue的全局api,它主要用来在下次dom更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的dom。
由于vue的更新机制是异步的,所以当数据修改之后,dom还停留在更新之前,此时想要获取更新后的dom,可以使用nextTick,表示的是下次dom更新循环结束后执行的回调。
应用场景:created 中获取dom可以使用nextTick
Document
- {{item}}