摘要:設計為單線程設計為單線程還是跟他的用途有關試想一下如果設計為多線程那么同時修改和刪除同一個瀏覽器又該如何執行需要異步我在執行但用戶不知道你好啊上圖例子循環耗時會很久這意味著用戶得不到你好啊的響應就會下意識會認為瀏覽器卡死了所以必須要有異步通
js設計為單線程
js設計為單線程還是跟他的用途有關js需要異步
試想一下 如果js設計為多線程 那么同時修改和刪除同一個dom 瀏覽器又該如何執行?
for (var i=0;i<9999;i++){ console.log("我在執行 但用戶不知道") } console.log("你好啊")
上圖例子 for循環耗時會很久一方面代碼慢慢跑著 另一方面用戶已經抓狂 js事件循環 (說白了不斷執行倆步驟) 一、歸類
這意味著 用戶得不到 "你好啊" 的響應 就會下意識會認為瀏覽器卡死了 所以js必須要有異步
js通過事件循環來實現異步 這也是js的運行機制
遇到同步任務直接執行,遇到異步任務分類為宏任務(macro-task)和微任務(micro-task)。
宏任務:整體的Script setTimeout setInterval
微任務:Promise process.nextTick
請看示例代碼:
// 這是一個同步任務 console.log("1") --------> 直接被執行 目前打印結果為:1 // 這是一個宏任務 setTimeout(function () { --------> 整體的setTimeout被放進宏任務列表 console.log("2") 目前宏任務列表記為【s2】 }); new Promise(function (resolve) { // 這里是同步任務 console.log("3"); --------> 直接被執行 resolve(); 目前打印結果為:1、3 // then是一個微任務 }).then(function () { --------> 整體的then[包含里面的setTimeout]被放進微任務列表 console.log("4") 目前微任務列表記為【t45】 setTimeout(function () { console.log("5") }); });
第一輪小結: 執行到這里的結果:1、3 宏任務列表如下: setTimeout(function () { console.log("2") }); 微任務列表如下: then(function () { console.log("4") setTimeout(function () { console.log("5") }); });二、有微則微,無微則宏
如果微任務列表里面有任務 會執行完畢后在執行宏任務 (ps:開篇有流程圖)
瀏覽器瞅了一眼微任務列表 發現里面有微任務 就開始全部執行 then(function () { console.log("4") --------> 直接被執行 目前打印結果為:1、3、4 setTimeout(function () { --------> 被放進宏任務列表了 console.log("5") 目前宏任務列表記為【s2、s5】 }); }); 瀏覽器發現微任務執行完畢了 開始執行宏任務列表 setTimeout(function () { console.log("2") --------> 直接被執行 目前打印結果為:1、3、4、2 }); setTimeout(function () { console.log("5") --------> 直接被執行 目前打印順序為: 1、3、4、2、5、5 }); 最終結果為: 1、3、4、2、5三、總結 + 實戰
反復執行以上步驟 就是事件循環(event loop)
一定要分的清任務類型 (宏任務 和 微任務)
TIP: 為了容易辨別起名為p1(p開頭 里面打印1) process.nextTick(function() { --------> 被放微任務列表 console.log("1"); 微任務列表記為:【p1】 }) new Promise(function (resolve) { console.log("2"); --------> 直接執行 resolve(); 目前打印順序為:2 }).then(function () { --------> 整體的then被放進微任務列表[包含其中的setTimeout 4] console.log("3"); 微任務列表記為:【p1 t34】 setTimeout(function () { console.log("4") }); }); setTimeout(function () { --------> 被放宏任務列表 console.log("5") 宏任務列表記為:【s5】 }); new Promise(function (resolve) { setTimeout(function () { --------> 被放宏任務列表 console.log("6") 宏任務列表記為:【s5 s6】 }); resolve() }).then(function () { --------> 整體的then被放進微任務列表[包含其中的setTimeout和其中的多層嵌套] setTimeout(function () { 微任務列表記為:【p1 t34 t789】 console.log("7") new Promise(function (resolve) { setTimeout(function () { console.log("8") }); resolve() }).then(function () { setTimeout(function () { console.log("9") }); }); }); }); console.log("10") --------> 直接執行 目前打印順序為:2、10
第一輪小結: 執行結果為:2、10 宏任務列表如下: // s5 setTimeout(function () { console.log("5") }); //s6 setTimeout(function () { console.log("6") }); 微任務列表如下: // p1 process.nextTick(function() { console.log("1"); }) // t34 then(function () { console.log("3"); setTimeout(function () { console.log("4") }); }); // t789 then(function () { setTimeout(function () { console.log("7") new Promise(function (resolve) { setTimeout(function () { console.log("8") }); resolve() }).then(function () { setTimeout(function () { console.log("9") }); }); });
開始執行第二輪: 有微任務 先執行微任務 將微任務列表代碼塊搬下來 // p1 process.nextTick(function() { --------> 執行p1 console.log("1"); 目前打印順序為:2、10、1 }) // t34 then(function () { console.log("3"); --------> 直接執行 目前打印順序為:2、10、1、3 setTimeout(function () { --------> 被放宏任務列表 console.log("4") 宏任務列表記為:【s5 s6 s4】 }); }); // t789 then(function () { setTimeout(function () { --------> 被放宏任務列表 console.log("7") 宏任務列表記為:【s5 s6 s4 s789】 new Promise(function (resolve) { setTimeout(function () { console.log("8") }); resolve() }).then(function () { setTimeout(function () { console.log("9") }); }); }); }) 微任務執行完畢了 該執行我們的宏任務列表了 因為微任務里面包含一部分宏任務 所以現在的宏任務列表已經增加了 現在把當前的宏任務列表搬下來 //s5 setTimeout(function () { --------> 執行s5 console.log("5") 目前打印順序為:2、10、1、3、5 }); //s6 setTimeout(function () { --------> 執行s6 console.log("6") 目前打印順序為:2、10、1、3、5、6 }); //s4 setTimeout(function () { --------> 執行s4 console.log("4") 目前打印順序為:2、10、1、3、5、6、4 }); // s789 setTimeout(function () { --------> 執行s789 console.log("7") 目前打印順序為:2、10、1、3、5、6、4、7 new Promise(function (resolve) { setTimeout(function () { --------> 被放宏任務列表 console.log("8") 宏任務列表記為:【s8】 }); resolve() }).then(function () { --------> 整體的then被放微任務列表[包含里面的setTimeout] setTimeout(function () { 微任務列表記為:【t9】 console.log("9") }); }); });
再次小結: 當前結果:2、10、1、3、5、6、4、7 馬上就要執行完了心里萬分激動啊 ( 瀏覽器的內心獨白 ^▽^ ...) 宏任務列表如下: // s8 setTimeout(function () { console.log("8") }); 微任務列表如下: // t9 then(function () { setTimeout(function () { console.log("9") }); }); 繼續執行 依舊遵循有微則微 無微則宏 瀏覽器發現有一條微任務 那就開始執行吧~ //t9 then(function () { setTimeout(function () { --------> 執行t9 把里面的setTimeout放入宏任務列表 console.log("9") 宏任務列表記為:【s8 s9】 }); }); 微任務列表執行完畢 開始執行宏任務(宏任務剛剛又有新增哦~[s9]) // s8 setTimeout(function () { --------> 執行s8 console.log("8") 目前打印順序為:2、10、1、3、5、6、4、7、8 }); // s9 setTimeout(function () { --------> 執行s9 console.log("9") 目前打印順序為:2、10、1、3、5、6、4、7、8、9 }); 到這里 微任務列表 和 宏任務列表均為空 就執行完畢了
再此留下一道沒有答案的題供練手
new Promise(function (resolve) { console.log("1"); resolve(); }).then(function () { setTimeout(function () { console.log("2") }); }); setTimeout(function () { console.log("3") process.nextTick(function() { console.log("4"); }) process.nextTick(function() { console.log("5"); }) }); new Promise(function (resolve) { console.log("6"); resolve(); setTimeout(function () { console.log("7") new Promise(function (resolve) { console.log("8"); resolve(); }).then(function () { setTimeout(function () { console.log("9") }); }); }); }).then(function () { setTimeout(function () { console.log("10") }); new Promise(function (resolve) { console.log("11"); resolve(); }).then(function () { setTimeout(function () { console.log("12") }); }); });
本人學識有限 文章多有不足
若有錯誤 請大方指出 以免誤導他人
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104037.html
摘要:規范中定義了瀏覽器何時進行渲染更新,了解它有助于性能優化。結合一些資料,對上邊規范給出一些理解有誤請指正每個線程都有自己的。列為,列為,列為。我們都知道是單線程,渲染計算和腳本運行共用同一線程網絡請求會有其他線程,導致腳本運行會阻塞渲染。 本文轉自blog 轉載請注明出處 異步的思考 event loops隱藏得比較深,很多人對它很陌生。但提起異步,相信每個人都知道。異步背后的靠山就是...
摘要:我不該動你的,寫在前面的話本意是想好好研究下,看了幾篇博客后,才意識到作為前端打字員的我有多無知,這坑忒深了。這樣的話,如果是第一種解釋,應該在運行之前,頁面就變成了紅色否則就應該采取第二種解釋。 我不該動你的,Event Loops 寫在前面的話 本意是想好好研究下 Event Loops, 看了幾篇博客后,才意識到作為前端打字員的我有多無知,這坑忒深了。 macrotask?,mi...
摘要:但是導致了很明顯的性能問題。上述兩個例子其實是在這個中找到的,第一個使用的版本是,這個版本的實現是采用了,而后因為的里的有,于是尤雨溪更改了實現,換成了,也就是后一個所使用的。后來尤雨溪了解到是將回調放入的隊列。 結論 對于event loop 可以抽象成一段簡單的代碼表示 for (macroTask of macroTaskQueue) { // 1. Handle cur...
摘要:但是導致了很明顯的性能問題。上述兩個例子其實是在這個中找到的,第一個使用的版本是,這個版本的實現是采用了,而后因為的里的有,于是尤雨溪更改了實現,換成了,也就是后一個所使用的。后來尤雨溪了解到是將回調放入的隊列。 結論 對于event loop 可以抽象成一段簡單的代碼表示 for (macroTask of macroTaskQueue) { // 1. Handle cur...
閱讀 2070·2021-10-11 10:59
閱讀 928·2021-09-23 11:21
閱讀 3553·2021-09-06 15:02
閱讀 1614·2021-08-19 10:25
閱讀 3370·2021-07-30 11:59
閱讀 2365·2019-08-30 11:27
閱讀 2580·2019-08-30 11:20
閱讀 2969·2019-08-29 13:15