JS分爲同步任務和異步任務,好比:ajax
// 同步任務
console.log('start');
function first() {
console.log('first');
second();
}
function second() {
console.log('second');
}
first();
// 異步任務
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
})
process.nextTick(function() {
console.log('nextTick');
})
複製代碼
同步任務都在主線程上執行,造成一個執行棧promise
以上同步任務的執行過程圖解: 瀏覽器
主線程以外,事件觸發線程管理着一個消息隊列,只要異步任務有了運行結果,就在任務隊列之中放置一個事件。
一旦執行棧中的全部同步任務執行完畢(此時JS引擎空閒),系統就會讀取消息隊列,將可運行的異步任務添加到可執行棧中,開始執行。bash
Promise.resolve().then(function() {
console.log('promise1');
})
console.log('end');
複製代碼
then
;console.log('end')
;console.log('promise1')
;end, promise1
瀏覽器爲了可以使得JS內部task與DOM任務可以有序的執行,會在一個task執行結束後,在下一個 task執行開始前,對頁面進行從新渲染(task->渲染->task->...)
屬於宏任務的有:setTimeout,setInterval等與timer有關的異步
微任務是一個任務隊列,這個隊列的執行順序是在清空執行棧以後。
屬於微任務的有Promise,process.nextTick,ajax等
process.nextTick的概念和then不太同樣,process.nextTick是加入到執行棧底部,因此和其餘的表現並不一致,屬於執行棧的一部分
函數
setTimeout(function() {
console.log('setTimeout');
})
new Promise(function(resolve) {
console.log('promise');
resolve();
}).then(function() {
console.log('then');
})
console.log('console');
複製代碼
setTimeout
,那麼將其回調函數註冊後分發到宏任務Event Queuenew Promise
當即執行console.log('promise');
then
函數分發到微任務的消息隊列中console.log('console')
,當即執行then
函數拿到主線程執行console.log('then')
setTimeout
promise, console, then, setTimeout
到此就結束了。oop
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
複製代碼