天天看點

web前端進階JavaScript - JavaScript中事件(任務)循環機制EventLoop及面試題

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及面試題

繼續閱讀