2、明确几点:
setTimeout
、DOM Event
、HttpRequest
、setInterval
、setImmediate(Node.js独有)
的回调、I/O
操作、UI
渲染均会被加载到消息队列(macrotask
宏任务)。
Promise
的回调、MutationObserver
、process.nextTick(Node.js独有)
会被加载到任务队列(microtask
微任务)。
- 任务队列优先级高于消息队列,也就是微任务优先级高于宏任务。
3、例子
new Promise(function (resolve, reject) {
resolve();
setTimeout(function () {
console.log(1);
}, 0);
console.log(2);
}).then(function () {
console.log(3);
}).then(function () {
console.log(4);
});
console.log(5); // 打印结果:2 5 3 4 1,其中setTimeout被加到消息队列,then回调被加到任务队列,先执行。
setTimeout(() => {
console.log("200");
}, 200);
setTimeout(() => {
console.log("100");
}, 100); // 100 200,等待执行的时间越短,越在队列前面,而不管在script中的顺序
setTimeout(() => {
console.log("2");
}, 2);
setTimeout(() => {
console.log("1");
}, 1); // 当等待时间过短时,或者说队列里两个item的间隔时间过短时,两者谁先执行并不确定,多数情况下打印1 2,即正常执行,少数情况下会打印 2 1
setTimeout(() => {
console.log(1);
new Promise((resolve, reject) => {
console.log(2);
resolve();
})
.then(() => {
setTimeout(() => {
console.log(4);
});
console.log(3);
})
.then(() => {
console.log(7);
});
console.log(5);
});
console.log(6); // 6 1 2 5 3 7 4,任务队列新插入消息队列,要先等任务队列所有任务执行完成,再执行下一个消息队列
setTimeout(() => {
console.log(1);
new Promise((resolve, reject) => {
console.log(2);
resolve();
})
.then(() => {
setTimeout(() => {
new Promise((resolve, reject) => {
console.log(4);
resolve();
}).then(() => {
console.log(8);
});
});
console.log(3);
})
.then(() => {
console.log(7);
});
console.log(5);
});
console.log(6); // 6 1 2 5 3 7 4 8,微任务属于宏任务,当前宏任务执行完才会执行下一个宏任务