「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战」
前言
单线程和异步请看:juejin.cn/post/699988…
微任务宏任务是前端的基础功底,有必要了解一下
js任务分两种微任务宏任务
-
宏任务(macrotasks) 宏任务一般包括:整体代码script,setTimeout,setInterval、setImmediate。
-
和微任务(microtasks) 微任务一般包括:原生Promise(有些实现的promise将then方法放到了宏任务中)、process.nextTick、Object.observe(已废弃)、 MutationObserver
下面先上代码
console.log(1)
setTimeout(()=>{
console.log(2)
},0)
console.log(3)
Promise.resolve().then(()=>{
console.log(4);
setTimeout(()=>{
console.log(5);
})
})
console.log(6)
//结果: 1 3 6 4 2 5
看结果是不是有点意外,通常除了同步 代码外,setTimeout 和 promise 都是异步代码,按照轮训队列,按说是先进先出的。2应该在4前面。 但是promist的then确先执行啦, 这是为什么呢,其实就是前面说的,promist是微任务,setTimeout是宏任务,规则是 同一层级的代码中,执行顺序为,先同步 -> 微任务 -> 宏任务
我们再看一个例子:
setTimeout(()=>{
console.log(0)
},0)
new Promise(resolve => {
console.log("1");
for(let i = 0;i<999999999; i++){
i === 999999999 && resolve();
}
console.log("2");
}).then(() => {
console.log("3");
});
//结果为 1 2 0
这里 根据你的电脑配置,1 2 之后会等一段时间才会执行0,不管你时间再长 setTimeout,都得等着。
然后我们再看这个
setTimeout(()=>{
console.log(0)
},0)
setTimeout(()=>{
new Promise(resolve => {
console.log("1");
for(let i = 0;i<999999999; i++){
i === 999999999 && resolve();
}
console.log("2");
}).then(() => {
console.log("3");
});
},0)
//结果为0 1 2
然后我们尝试修改第一个定时器的时间为100
setTimeout(()=>{
console.log(0)
},100 )
setTimeout(()=>{
new Promise(resolve => {
console.log("1");
for(let i = 0;i<999999999; i++){
i === 999999999 && resolve();
}
console.log("2");
}).then(() => {
console.log("3");
});
},0)
//结果为 1 2 0
得出:如果有两个相同时间的定时器则上面的先执行下面的后执行
总结:
有关定时器
- 定时器模块,到达时间点将其放入宏任务队列
- 如果主线程没有任务则执行,如果有则等待执行完成后再继续执行
- 如果有两个相同时间的定时器则上面的先执行下面的后执行
- 如果两个时间不同的定时器则时间短的先执行时间长的后执行
有关Promise
- promise的构造函数为同步任务
- 执行顺序永远为:同步=>微任务=>宏任务
- 在嵌套代码中可能出现宏任务中有同步、宏任务、微任务,这时将他们放到下一次执行中的队列/主线程等待执行
setTimeout(() => {
console.log("定时器");
setTimeout(() => {
console.log("timeout timeout");
}, 0);
new Promise(resolve => {
console.log("settimeout Promise");
resolve();
}).then(() => {
console.log("settimeout then");
});
}, 0);
new Promise(resolve => {
console.log("Promise");
resolve();
}).then(() => {
console.log("then");
});
console.log("ssss");
执行顺序:Promise=>ssss=>then=>定时器=>settimeout Promise=>settimeout then=>timeout timeout
宏任务与微任务
- javaScript是单线程语言
- 所以在同一时间只能执行一个任务,称为主线程,用来执行同步任务
- 同时还有两个任务列表用于存放异步任务,宏任务、微任务
- 执行顺序为:主线程=>微任务=>宏任务
参考文章
- JavaScript 操作宏任务与微任务 www.jb51.net/article/215…
- 译文:JS事件循环机制(event loop)之宏任务、微任务 segmentfault.com/a/119000001…
- JS的宏任务和微任务 www.mybj123.com/8384.html