JavaScript中的異步與同步詳解
基本概念
- 消息隊列中的任務(wù)分為
宏任務(wù)
與微任務(wù)
; - 調(diào)用棧也可以稱為
主線程
單線程:
- 單線程指的是只有一個主線程的線程的語言。也就是說,它并不能像JAVA語言那樣,多個線程并發(fā)執(zhí)行。
- JavaScript就是一個單線程的語言
為什么js是單線程?如果一個線程在一個節(jié)點中添加內(nèi)容,另一個線程要刪除這個節(jié)點。所以為了不必要的麻煩,js就是一門單線程語言。
js的異步執(zhí)行分析:
- 拿現(xiàn)實生活來舉例,比如一個人在家(將一個人比作單線程),你既要煮飯又要炒菜。
- 這里我們把煮飯算作一個異步的任務(wù),因為煮飯是一個比較耗時的任務(wù)(一般像比較耗時或不確定執(zhí)行時間的任務(wù),比如定時器,網(wǎng)絡(luò)請求,事件執(zhí)行 都是異步執(zhí)行),其次你沒炒完菜是不會
- 去吃飯的(也就是主線程任務(wù)沒有完成,是不會執(zhí)行異步任務(wù)的)。
- 那么你可以怎么做呢?你可以把煮飯的任務(wù)交給電飯煲處理。
- 先把米放入電飯煲交給了電飯煲處理,再去炒菜,炒完菜再去把煮好的飯取出來。
- 將飯交給電飯煲處理相當(dāng)于開啟了一個異步的任務(wù),電飯煲就是處理這個異步任務(wù)的模塊。飯煮好了會自動跳轉(zhuǎn),這就相當(dāng)于異步任務(wù)被對應(yīng)的模塊解析好了會自動放入消息隊列,等待事件循
- 環(huán)調(diào)入主線程執(zhí)行(前提是主線程任務(wù)全部執(zhí)行完畢)。
- 主線程任務(wù)執(zhí)行完成,會通過不斷的循環(huán)消息隊列,來執(zhí)行其中的任務(wù)。
- 也就是你把炒菜完了,你就會不斷的觀察飯是否跳轉(zhuǎn)(也就是循環(huán)消息隊列看是否有任務(wù)),如果有就把飯裝到碗里開始吃飯,此時任務(wù)就全部完成。
- 但是干活的始終還是一個人,這就是單線程的異步執(zhí)行過程。
圖解:
代碼演示:
console.log("遇到煮飯任務(wù),將飯放入電飯煲"); //使用setTimeout模擬煮飯 setTimeout(()=>{ console.log("飯已經(jīng)煮熟,等待飯被取出"); },0); console.log("開始炒菜任務(wù)");
你以為的執(zhí)行順序:“遇到煮飯任務(wù),將飯放入電飯煲 ” -> “飯已經(jīng)煮熟,等待飯被取出 -> ”開始炒菜任務(wù)“
但是你想想這樣符合邏輯嗎,你會等飯熟練才開始炒菜嗎?
最終執(zhí)行順序:“遇到煮飯任務(wù),將飯放入電飯煲 ” -> “開始炒菜任務(wù)” -> “飯已經(jīng)煮熟,等待飯被取出”
顯然js都知道你認(rèn)為的執(zhí)行順序是不符合邏輯的。這里setTimeout就是一個異步任務(wù),其中的箭頭函數(shù)就是異步完成后回調(diào)的函數(shù)。
解釋疑惑:
JavaScript既然是單線程語言,那么為什么同時可以執(zhí)行多個任務(wù)(同時煮飯炒菜)?
你可能會想這TM不是廢話嗎,煮飯交給電飯煲了啊。
確實沒錯,煮飯任務(wù)交給電飯煲了,那么在js中是誰去處理這些異步的任務(wù)呢?
前面異步任務(wù)分析有說到,異步任務(wù)會被對應(yīng)模塊解析(飯被電飯煲模塊解析)。那么這就和宿主有關(guān)系了,js一般都是運行在游覽器上(當(dāng)然有node.js)
也就是寄生在游覽器上,那么宿主就是游覽器。所以是宿主提供的模塊去處理這些異步任務(wù),使得js可以實現(xiàn)與其他語言類似的多線程操作。
補充異步任務(wù)執(zhí)行順序:
而常見的promise,async,await 執(zhí)行放入的是微任務(wù)隊列中,主線程的代碼執(zhí)行完后,會優(yōu)先循環(huán)微任務(wù)隊列的代碼,再是宏任務(wù)隊列。主線程 > 微任務(wù) > 宏任務(wù)注意??!宏任務(wù)隊列與微任務(wù)隊列的任務(wù)都是誰先進入隊列誰先執(zhí)行。
js的同步執(zhí)行解析
代碼由上至下依次執(zhí)行。前面任務(wù)在執(zhí)行,后面代碼必須排隊等待。就如上面的例子如果不做異步處理,讓任務(wù)同步執(zhí)行就會一直卡在做飯的地方,等飯煮好了才能去炒菜。
到此這篇關(guān)于JavaScript中的異步與同步詳解的文章就介紹到這了,更多相關(guān)JavaScript異步與同步內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript基礎(chǔ)之Array?forEach使用示例
這篇文章主要為大家介紹了JavaScript基礎(chǔ)之Array?forEach使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12圖文詳解Heap Sort堆排序算法及JavaScript的代碼實現(xiàn)
這篇文章以圖文詳解Heap Sort堆排序算法及JavaScript的代碼實現(xiàn),堆排序算法基于類二叉樹的堆數(shù)據(jù)結(jié)構(gòu),需要的朋友可以參考下2016-05-05Javascript學(xué)習(xí)筆記一 之 數(shù)據(jù)類型
在接觸每一門編程語言之前,首先明白我們程序設(shè)計要處理的是數(shù)據(jù),而數(shù)據(jù)又用數(shù)據(jù)類型將其區(qū)分。2010-12-12JS阻止冒泡事件以及默認(rèn)事件發(fā)生的簡單方法
這篇文章主要介紹了JS阻止冒泡事件以及默認(rèn)事件發(fā)生的簡單方法,有需要的朋友可以參考一下2014-01-01