摘要:接下來處理微任務隊列,打印,后面一個不會有任何打印,但是會執行執行后面的代碼打印進入第二次事件循環,執行宏任務隊列打印
事件循環機制
理解js的事件循環機制,能夠很大程度的幫我們更深層次的理解平時遇到的一些很疑惑的問題
簡單版本下面來看一段代碼,想想它的結果和你的結果是否一樣
setTimeout(function() { console.log(1) }, 0) console.log(2) // 執行結果是 2 1
我們可以將js的任務分為同步任務和異步任務, 按照這種分類js的執行機制如下
任務執行隊列分為同步任務隊列和異步任務隊列
代碼執行時,遇到同步代碼,會被直接推入同步任務隊列并依次執行
遇到異步代碼(如setTimeout、setInterval), 會被直接推入異步任務隊列
當同步任務隊列執行完畢,這個時候異步任務隊列的任務會被依次推入同步任務隊列并依次執行
所以上面的代碼執行的時候, setTimeout()不會被立即執行,會被推到異步任務隊列里面, 之后再執行console.log(2), 同步任務隊列任務執行完畢之后,會去異步任務隊列的任務會被依次推到 同步任務隊列并執行
終極版本下面來看一段代碼,想想它的結果和你的結果是否一樣
setTimeout(function() { console.log(1) }, 0) new Promise(function(resolve, reject) { console.log(2) resolve() }).then((res) => { console.log(3) }) console.log(4) // 執行結果是 2 4 3 1
js異步任務按照準確的劃分,應該將任務分為
宏任務: setTimeout、setInterval
微任務: 例如Promise.then方法。注意new Promsie()的時候是同步,立即執行。
注意: 現在有三個隊列: 同步隊列(也稱執行棧)、宏任務隊列、微任務隊列
所以針對這種機制,js的事件循環機制應該是這樣的
遇到同步代碼,依次推入同步隊列并執行
當遇到setTimeout、setInterval,會被推到宏任務隊列
如果遇到.then,會被當作微任務,被推入微任務隊列
同步隊列執行完畢,然后會去微隊列取任務,直到微隊列清空。然后檢查宏隊列,去宏隊列取任務,并且每一個宏任務執行完畢都會去微隊列跑一遍,看看有沒有新的微任務,有的話再把微任務清空。這樣依次循環
console.log(1); setTimeout(() => { console.log("setTimeout"); }, 0); let promise = new Promise(resolve => { console.log(3); resolve(); }).then(data => { console.log(100); }).then(data => { console.log(200); }); console.log(2);
所以對于以上的代碼執行流程如下:
遇到同步任務先輸出1。
setTimeout是宏任務,會先放到宏任務隊列中。
new Promise是立即執行的,所以會先輸出3。
而Promise.then是微任務,會依次排列到微任務隊列中,繼續向下執行輸出2。
現在執行棧中的任務已經清空,再將微任務隊列清空,依次輸出100和200。
然后每次取出一個宏任務,因為現在只有一個宏任務,所以最后輸出setTimeout。
async/await async當我們在函數前使用async的時候,使得該函數返回的是一個Promise對象
async function test() { return 1 // async的函數會在這里幫我們隱士使用Promise.resolve(1) } // 等價于下面的代碼 function test() { return new Promise(function(resolve, reject) { resolve(1) }) }
可見async只是一個語法糖,只是幫助我們返回一個Promise而已
awaitawait表示等待,是右側「表達式」的結果,這個表達式的計算結果可以是 Promise 對象的值或者一個函數的值(換句話說,就是沒有特殊限定)。并且只能在帶有async的內部使用
使用await時,會從右往左執行,當遇到await時,會阻塞函數內部處于它后面的代碼,去執行該函數外部的同步代碼,當外部同步代碼執行完畢,再回到該函數內部執行剩余的代碼, 并且當await執行完畢之后,會先處理微任務隊列的代碼
下面來看一個栗子:
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" )
下面是在chrome瀏覽器上輸出的結果
使用事件循環機制分析:
首先執行同步代碼,console.log( "script start" )
遇到setTimeout,會被推入宏任務隊列
執行async1(), 它也是同步的,只是返回值是Promise,在內部首先執行console.log( "async1 start" )
然后執行async2(), 然后會打印console.log( "async2" )
從右到左會執行, 當遇到await的時候,阻塞后面的代碼,去外部執行同步代碼
進入 new Promise,打印console.log( "promise1" )
將.then放入事件循環的微任務隊列
繼續執行,打印console.log( "script end" )
外部同步代碼執行完畢,接著回到async1()內部, 由于async2()其實是返回一個Promise, await async2()相當于獲取它的值,其實就相當于這段代碼Promise.resolve(undefined).then((undefined) => {}),所以.then會被推入微任務隊列, 所以現在微任務隊列會有兩個任務。接下來處理微任務隊列,打印console.log( "promise2" ),后面一個.then不會有任何打印,但是會執行
執行后面的代碼, 打印console.log( "async1 end" )
進入第二次事件循環,執行宏任務隊列, 打印console.log( "setTimeout" )
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100510.html
摘要:由于是單線程的,這些方法就會按順序被排列在一個單獨的地方,這個地方就是所謂執行棧。事件隊列每次僅執行一個任務,在該任務執行完畢之后,再執行下一個任務。 Event Loop 是 JavaScript 異步編程的核心思想,也是前端進階必須跨越的一關。同時,它又是面試的必考點,特別是在 Promise 出現之后,各種各樣的面試題層出不窮,花樣百出。這篇文章從現實生活中的例子入手,讓你徹底理解 E...
摘要:下面開始分析開頭的代碼第一輪事件循環流程整體作為第一個宏任務進入主線程,遇到,輸出遇到函數聲明,聲明暫時不用管遇到,其回調函數被分發到微任務中。我們記為遇到,其回調函數被分發到宏任務中。 先上一道常見的筆試題 console.log(1); async function async1() { console.log(2); await async2(); con...
摘要:圖片轉引自的演講和兩個定時器中回調的執行邏輯便是典型的機制。異步編程關于異步編程我的理解是,在執行環境所提供的異步機制之上,在應用編碼層面上實現整體流程控制的異步風格。 問題背景 在一次開發任務中,需要實現如下一個餅狀圖動畫,基于canvas進行繪圖,但由于對于JS運行環境中異步機制的不了解,所以遇到了一個棘手的問題,始終無法解決,之后在與同事交流之后才恍然大悟。問題的根節在于經典的J...
摘要:下面開始分析開頭的代碼第一輪事件循環流程整體作為第一個宏任務進入主線程,遇到,輸出遇到函數聲明,聲明暫時不用管遇到,其回調函數被分發到微任務中。我們記為遇到,其回調函數被分發到宏任務中。 先上一道常見的筆試題 console.log(1); async function async1() { console.log(2); await async2(); con...
摘要:何為事件循環機制的任務分兩種,分別是同步任務和異步任務。如上圖所示主線程在執行代碼的時候,遇到異步任務進入并注冊回調函數,有了運行結果后將它添加到事件隊列中,然后繼續執行下面的代碼,直到同步代碼執行完。 我們知道,JavaScript作為瀏覽器的腳本語言,起初是為了與用戶交互和操作DOM,為了避免因為同時操作了同一DOM節點而引起沖突,被設計成為一種單線程語言。而單線程語言最大的特性就...
閱讀 1010·2021-11-22 13:52
閱讀 924·2019-08-30 15:44
閱讀 570·2019-08-30 15:43
閱讀 2424·2019-08-30 12:52
閱讀 3473·2019-08-29 16:16
閱讀 637·2019-08-29 13:05
閱讀 2943·2019-08-26 18:36
閱讀 1975·2019-08-26 13:46