Js中的事件循環機制EventLoop
- 在JavaScript代碼自上而下執行過程中,分為同步任務和異步任務,異步任務又分為異步微任務和異步宏任務,同步任務也是宏任務。
- 【常見的異步微任務】
- promise
- async/await
- requestAnimationFrame
- 【常見的異步宏任務】
- 定時器setTimeout
- ajax(HTTP網絡請求)
- 事件綁定
- …
- 在主線程自上而下執行js代碼時,同步宏任務會優先執行,如果遇到上述異步任務,不會立即執行,而是把這些異步任務存放到EventQueue任務隊列中進行排隊等待,主線程中的同步任務繼續向下執行
- 當所有同步任務執行完成後,再優先執行所有異步微任務,待所有異步微任務執行完成後,最後再執行異步宏任務
- 在執行過程中會嚴格按照該順序執行
- 即使在同步任務沒有執行完,但異步任務中已經有到達執行條件了,那也不能執行,必須要等待同步任務執行完成
- 不管什麼時候放置的微任務,也不管異步宏任務是否已經到達執行條件了,隻要異步微任務存在,就永遠不會執行異步宏任務
- 事件循環機制EventLoop:主線程自上而下,已經執行完所有同步任務,主線程空閑下來,開始到EventQueue任務隊列中找異步任務(優先查找微任務),找到任務後拿到主線程中執行,此時主線程又被占用不能處理其他事情,當這個異步任務執行完,主線程又空閑,繼續到EventQueue中查找其它異步任務執行,這就是事件循環機制。
web前端進階JavaScript - JavaScript中事件(任務)循環機制EventLoop及面試題
關于同步異步的一些面試題
let body = document.body;
body.addEventListener('click', function(){
Promise.resolve().then(() => {
console.log(1);
});
console.log(2);
});
body.addEventListener('click', function(){
Promise.resolve().then(() => {
console.log(3);
});
console.log(4);
});
//答案:2 1 4 3
//======================================================================
console.log('start');
let intervalId;
Promise.resolve().then(() => {
console.log('p1');
}).then(() => {
console.log('p2');
});
setTimeout(() => {
Promise.resolve().then(() => {
console.log('p3');
}).then(() => {
console.log('p4');
});
intervalId = setInterval(() => {
console.log('interval');
}, 3000);
console.log('timeout1');
}, 0);
//答案:start p1 p2 timeout1 p3 p4 interval....
//======================================================================
setTimeout(() => {
console.log('a');
});
Promise.resolve().then(() => {
console.log('b');
}).then(() => {
return Promise.resolve('c').then(data => {
setTimeout(() => {
console.log('d')
});
console.log('f');
return data;
});
}).then(data => {
console.log(data);
});
//答案:b f c a d
//======================================================================
function func1() {
console.log('func1 start');
return new Promise(resolve => {
resolve('OK');
});
}
function func2() {
console.log('func2 start');
return new Promise(resolve => {
setTimeout(() => {
resolve('OK');
}, 10);
});
}
console.log(1);
setTimeout(async () => {
console.log(2);
await func1();
console.log(3);
}, 20);
for (let i = 0; i < 90000000; i++) {} //循環完大于80ms左右
console.log(4);
func1().then(result => {
console.log(5);
});
func2().then(result => {
console.log(6);
});
setTimeout(() => {
console.log(7);
}, 0);
console.log(8);
//答案:1 4 [func1 start] [func2 start] 8 5 2 [func1 start] 3 7 6
//======================================================================
setTimeout(() => {
console.log(1);
}, 20);
console.log(2);
setTimeout(() => {
console.log(3);
}, 10);
console.log(4);
console.time('AA');
for (let i = 0; i < 90000000; i++) {
// do soming
}
console.timeEnd('AA'); //=>AA: 79ms 左右
console.log(5);
setTimeout(() => {
console.log(6);
}, 8);
console.log(7);
setTimeout(() => {
console.log(8);
}, 15);
console.log(9);
//答案:2 4 [AA:79ms] 5 7 9 3 1 6 8
//======================================================================
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
//答案:[script start] [async1 start] async2 promise1 [script end] [async1 end] prmise2 setTimeout
畫圖分析
web前端進階JavaScript - JavaScript中事件(任務)循環機制EventLoop及面試題
web前端進階JavaScript - JavaScript中事件(任務)循環機制EventLoop及面試題