一、微任务与宏任务
JS中的任务可分为以下两类
·macro-task(宏任务):包括整体代码script,setTimeout,setInterval
·micro-task(微任务):Promise.then,process.nextTick
JS执行过程优先执行所有宏任务,之后执行微任务,之后继续新的宏任务,之后又是微任务一直循环执行。
console.log('start');
new Promise(function(resolve) {
console.log('promise');
resolve();
}).then(function() {
console.log('then');
})
console.log('end');
依次输出start->promise->end->then
遇见第一个console属于宏任务直接输出,遇见promise属于宏任务直接输出,遇见then输入微任务放入微任务队列中,遇见最后的console属于宏任务直接输出,最后执行微任务队列中的then。
console.log('start');
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
new Promise(function(resolve) {
console.log('promise2');
resolve();
}).then(function() {
console.log('then');
})
})
console.log('end');
如果理解的话你可以尝试思考下上面代码会的输出顺序
start->promise1->end->promise2->then
二、异步
现在我们说JS处理异步的方式:
·同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
·当指定的事情完成时,Event Table会将这个函数移入Event Queue。
·主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
·上述过程会不断重复。
console.log('start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
console.log('end');
依次输出:start->end->setTimeout
遇见第一个console属于同步任务直接执行,遇见第二个setTimeout属于异步任务,进入Event Table并注册函数,0秒后推入Event Queue。遇见下一个console直接输出,同步任务执行完后。主进程执行Event Queue中的回调函数输出setTimeout
三、异步+微任务
知道了异步的执行方式,那异步与微任务同时出现的情况也可以分析。
console.log('start');
new Promise(function(resolve) {
setTimeout(() => {
console.log('setTimeout1');
}, 0);
resolve();
}).then(function() {
console.log('then');
setTimeout(() => {
console.log('setTimeout2');
}, 0);
})
setTimeout(() => {
console.log('setTimeout3');
}, 0);
console.log('end');
依次输出:start->end->then->setTimeout1->setTimeout3->setTimeout2
遇见console.log(‘start’)属于宏任务/同步任务直接执行,遇见Promise中的setTimeout属于宏任务/异步任务,进入Event Table并注册函数,0秒后推入Event Queue,遇见then,属于微任务推入微任务队列中,遇见最后一个setTimeout属于宏任务/异步任务,进入Event Table并注册函数,0秒后推入Event Queue,遇见console.log(‘end’)属于宏任务/同步任务之间执行,然后执行微任务中的then函数中的console.log(‘then’);属于宏任务/同步任务直接执行,然后setTimeout,进入Event Table并注册函数,0秒后推入Event Queue,然后依次执行进入Event Queue的三个console。
console.log('start');
new Promise(function(resolve) {
setTimeout(() => {
console.log('setTimeout1');
}, 0);
resolve();
}).then(function() {
new Promise(function(resolve) {
console.log('then1');
setTimeout(() => {
console.log('setTimeout2');
}, 0);
resolve();
}).then(function() {
console.log('then2');
setTimeout(() => {
console.log('setTimeout3');
}, 0);
})
})
setTimeout(() => {
console.log('setTimeout4');
}, 0);
console.log('end');
如果理解可以理解可以尝试上面较为复杂的代码
依次输出:start->end->then1->then2->setTimeout1->setTimeout4->setTimeout2->setTimeout3