新聞中心
js里的事件循環(huán)機制十分有趣。從很多面試題也可以看出來,考察簡單的setTimeout也就是考察這個機制的。

創(chuàng)新互聯(lián)建站主要為客戶提供服務(wù)項目涵蓋了網(wǎng)頁視覺設(shè)計、VI標志設(shè)計、成都營銷網(wǎng)站建設(shè)、網(wǎng)站程序開發(fā)、HTML5響應(yīng)式網(wǎng)站建設(shè)公司、移動網(wǎng)站建設(shè)、微商城、網(wǎng)站托管及網(wǎng)站維護、WEB系統(tǒng)開發(fā)、域名注冊、國內(nèi)外服務(wù)器租用、視頻、平面設(shè)計、SEO優(yōu)化排名。設(shè)計、前端、后端三個建站步驟的完善服務(wù)體系。一人跟蹤測試的建站服務(wù)標準。已經(jīng)為航空箱行業(yè)客戶提供了網(wǎng)站設(shè)計服務(wù)。
在之前,我只是簡單地認為由于函數(shù)執(zhí)行很快,setTimeout執(zhí)行時間即便為0也不會馬上輸出,而是等待函數(shù)執(zhí)行完后再輸出。這只對了一半。
實際上其運行機制就是js中的事件循環(huán)機制,在這個循環(huán)機制中呢,又與call Stack和task queue有關(guān)。
一、js事件循環(huán)機制
事件循環(huán)機制呢,簡單點來說,就是在執(zhí)行上下文的過程中,對函數(shù)的入棧和出棧。執(zhí)行前函數(shù)先入棧,執(zhí)行完后函數(shù)出棧。如若遇到了一些異步操作像回調(diào)函數(shù)以及ajax、setTimeout等,會先將他們交給瀏覽器的其他模塊去執(zhí)行,執(zhí)行完后,會把回調(diào)函數(shù)放入到taskqueue中。當(dāng)所有的call stack執(zhí)行完后再開始執(zhí)行task queue中的函數(shù)。
舉一個簡單的例子:
- console.log(1);
- setTimeout(function()
我們來看一下執(zhí)行的內(nèi)部過程
1. 執(zhí)行***句,放入call stack中,輸出 1
2. ***句出棧,執(zhí)行第二句,由于是異步執(zhí)行,交給其他模塊。
3. 執(zhí)行完后,將回調(diào)函數(shù)放入taskqueue中
4. 執(zhí)行下一句,同***步一樣,將語句入棧并執(zhí)行,輸出3
5. 語句出棧,此時call stack空了。開始執(zhí)行task queue任務(wù),輸出2
所以,輸出結(jié)果是
與預(yù)想一致。
二、進階
如果添加了Promise又如何工作呢?
我們知道,Promise的回調(diào)函數(shù)不是傳入的,而是使用then來調(diào)用的。因此,Promise中定義的函數(shù)應(yīng)該是馬上執(zhí)行的,then才是其回調(diào)函數(shù),放入queue隊列中。
還提到了一個重要的概念:
- macro-task包括:script(整體代碼), setTimeout, setInterval, setImmediate, I/O, UI rendering。
- micro-task包括:process.nextTick, Promises, Object.observe, MutationObserver
執(zhí)行順序:函數(shù)調(diào)用棧清空只剩全局執(zhí)行上下文,然后開始執(zhí)行所有的micro-task。當(dāng)所有可執(zhí)行的micro-task執(zhí)行完畢之后。循環(huán)再次執(zhí)行macro-task中的一個任務(wù)隊列,執(zhí)行完之后再執(zhí)行所有的micro-task,就這樣一直循環(huán)。
- (function test() {
- setTimeout(function() {console.log(4)}, 0);
- new Promise(function executor(resolve) {
- console.log(1);
- for( var i=0 ; i<10000 ; i++ ) {
- i == 9999 && resolve();
- }
- console.log(2);
- }).then(function() {
- console.log(5);
- });
- console.log(3);})()
執(zhí)行過程:
1. 遇到setTimeout,交給其他模塊執(zhí)行,執(zhí)行完后回調(diào)放入macro-task中
2. 遇到Promise,立即執(zhí)行里面的function,輸出1。
3. 循環(huán)開始,遇到resolve(),修改Promise狀態(tài)為fulfill。繼續(xù)執(zhí)行,輸出2。
4. 遇到then,將回調(diào)放入micro-task中。
5. 繼續(xù)執(zhí)行,輸出3。
6. call stack執(zhí)行完畢了。開始執(zhí)行micro-task中的回調(diào)函數(shù),輸出5。
7. micro-task執(zhí)行完畢,開始執(zhí)行macro-task中的回調(diào)函數(shù),輸出4。
8. 結(jié)束。
【本文為專欄作者“謝軍”的原創(chuàng)稿件,轉(zhuǎn)載可通過作者微信公眾號(jingfeng18)獲取聯(lián)系】
網(wǎng)頁名稱:前端開發(fā)JS:事件循環(huán)機制、調(diào)用棧以及任務(wù)隊列
標題鏈接:http://www.dlmjj.cn/article/dhohpsj.html


咨詢
建站咨詢
