單線程異步和event-loop

單線程異步

js是單線程異步的,單線程就是同一時間只做一件事,原因是避免dom操作的沖突,設想一下js是多線程的,然后多線程上的js都要操作一個dom,就會產生沖突。而僅僅是單線程的話,如果有一個請求要耗費很長時間時,瀏覽器就會卡在那里等待,這樣當然也不行,所以有了異步。

event-loop

那么異步要怎么運行?這就是接下來要說的event-loop(事件輪詢)
event-loop是js的運行機制,其執(zhí)行的方式如下:

image.png

1.同步和異步任務分別進入不同的執(zhí)行"場所",同步的進入主線程,異步的進入Event Table并注冊函數(shù)。
2.當指定的事情完成時,Event Table會將這個函數(shù)移入Event Queue。
3.主線程內的任務執(zhí)行完畢為空,會去Event Queue讀取對應的函數(shù),進入主線程執(zhí)行。
4.上述過程會不斷重復,也就是常說的Event Loop(事件循環(huán))。

除了廣義的同步任務和異步任務,我們對任務有更精細的定義:

macro-task(宏任務):包括整體代碼script,setTimeout,setInterval
micro-task(微任務):Promise,process.nextTick

注意:任務隊列分微任務和宏任務,先執(zhí)行全部的微任務,再執(zhí)行宏任務。

接下來看一下下面的案例:

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');

分析:

1、整個代碼塊作為一個宏任務,進入主線程,async1和async2函數(shù)定義,遇到console.log輸出script start;
2、遇到setTimeout() ,把它的回調函數(shù)放入宏任務(setTimeout1)。

微任務 宏任務
setTimeout1

3、遇到執(zhí)行async1(), 執(zhí)行async1,遇到console.log輸出async1 start;
4、然后遇到await async2(),執(zhí)行async2();
5、看到console.log輸出async2,之后沒有返回值,結束函數(shù),返回undefined,返回到async1的執(zhí)行上下文的await undefined,由于async函數(shù)使用await后得語句會被放入一個回調函數(shù)中,所以把下面的放入微任務中。

微任務 宏任務
async1=> await后面的語句 setTimeout1

6、結束async1,返回全局上下文,遇到Promise構造函數(shù),里面的執(zhí)行函數(shù)立馬執(zhí)行, 輸出promise1, 之后的回調函數(shù)進入微任務;

微任務 宏任務
async1=> await后面的語句 setTimeout1
new Promise() => 后的then

執(zhí)行完Promise(),遇到console.log,輸出script end,這里一個宏任務代碼塊執(zhí)行完畢。

7、主線程現(xiàn)在空閑下來后,執(zhí)行事件隊列中的微任務,遇到new Promise()后面的回調函數(shù),執(zhí)行代碼,輸出promise2(這里2個微任務的優(yōu)先級,promise高于async)。

8、看到async1中await后面的回調函數(shù),執(zhí)行代碼,輸出async1 end

9、此時微任務中的隊列為空,開始執(zhí)行隊列中的宏任務,遇到console.log,輸出setTimeout。
最后,執(zhí)行完成,最后結果為

script start 
async1 start 
async2
promise1
script end 
promise2 
async1 end
setTimeout

參考文章:
https://juejin.im/post/59e85eebf265da430d571f89

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容