理解js
的事件循環機制,可以很大程度的幫咱們更深層次的理解平時遇到的一些很疑惑的問題chrome
下面來看一段代碼,想一想它的結果和你的結果是否同樣promise
setTimeout(function() { console.log(1) }, 0) console.log(2) // 執行結果是 2 1
咱們能夠將js
的任務分爲同步任務和異步任務, 按照這種分類js
的執行機制以下瀏覽器
setTimeout、setInterval
), 會被直接推入異步任務隊列 因此上面的代碼執行的時候, setTimeout()
不會被當即執行,會被推到異步任務隊列裏面, 以後再執行console.log(2)
, 同步任務隊列任務執行完畢以後,會去異步任務隊列的任務會被依次推到 同步任務隊列並執行異步
下面來看一段代碼,想一想它的結果和你的結果是否同樣async
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()
的時候是同步,當即執行。注意: 如今有三個隊列: 同步隊列(也稱執行棧)、宏任務隊列、微任務隊列spa
因此針對這種機制,js
的事件循環機制應該是這樣的code
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);
因此對於以上的代碼執行流程以下:對象
setTimeout
是宏任務,會先放到宏任務隊列中。new Promise
是當即執行的,因此會先輸出3。Promise.then
是微任務,會依次排列到微任務隊列中,繼續向下執行輸出2。setTimeout
。當咱們在函數前使用async
的時候,使得該函數返回的是一個Promise
對象隊列
async function test() { return 1 // async的函數會在這裏幫咱們隱士使用Promise.resolve(1) } // 等價於下面的代碼 function test() { return new Promise(function(resolve, reject) { resolve(1) }) }
可見async
只是一個語法糖,只是幫助咱們返回一個Promise
而已
await
表示等待,是右側「表達式」的結果,這個表達式的計算結果能夠是 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' )