js async await
一、async
帶async關鍵字的函數,是聲明異步函數,返回值是promise對象,如果async關鍵字函數返回的不是promise,會自動用Promise.resolve()包裝。
async function test() { return ‘test‘ } test();
返回值為 Promise {<resolved>: "test"}。
二、await
await等待右側表達式的結果,這個結果是promise對象或者其他值。
如果它等到的不是一個 promise 對象,那 await 表達式的運算結果就是它等到的東西。
如果它等到的是一個 promise 對象,await 就忙起來了,它會阻塞後面的代碼,等著 promise 對象 resolve,然後得到 resolve 的值,作為 await 表達式的運算結果。
function test() { return new Promise(resolve => { setTimeout(() => resolve("test"), 2000); }); } const result = await test(); console.log(result); console.log(‘end‘)
由於test()造成的阻塞,console.log(‘end‘)會等到兩秒後執行
所以為了避免造成阻塞,await 必須用在 async 函數中,async 函數調用不會造成阻塞。
function test() {return new Promise(resolve => { setTimeout(() => resolve("test"), 2000); }); } async function test2() { const result = await test(); console.log(result); } test2(); console.log(‘end‘);
先執行console.log(‘end‘),兩秒後執行console.log(‘test‘)
如果await用在普通函數中,會報錯,如下:
三、async/await的執行順序
遇到await會阻塞後面的代碼,先執行async外面的同步代碼,同步代碼執行完,再回到async內部,繼續執行await後面的代碼。以下面的代碼分析:
async function test1() { console.log(‘start test1‘); console.log(await test2()); console.log(‘end test1‘); } async function test2() { console.log(‘test2‘); return ‘return test2 value‘ } test1(); console.log(‘start async‘); setTimeout(() => { console.log(‘setTimeout‘); }, 0); new Promise((resolve, reject) => { console.log(‘promise1‘); resolve(); }).then(() => { console.log(‘promise2‘); }); console.log(‘end async‘);
執行的結果
· 首先執行宏任務,執行test1函數,執行console.log(‘statr test1‘)
· 遇到await,先執行右邊test2中的console.log(‘test2‘),中斷了後面的代碼,執行test1外面的同步代碼
· 執行console.log(‘start async‘);
· 遇到setTimeout,推到到下個宏任務隊列中
· 執行Promise裏面的同步代碼console.log(‘promise1‘)
· 運行到promise().then,發現是promise對象,推到微任務隊列中
· 執行console.log(‘end async‘)
· test1外面的同步代碼執行結束後,回到test1中,console.log(await test2())執行完成後返回Promise {<resolved>: "return test2 value"},是promise對象,推到微任務隊列中
· 此時第一個宏任務結束,執行所有的微任務,因為微任務隊列先進先出,所以先執行console.log(‘promise2‘),後執行console.log(‘return test2 value‘)
· 執行test2完成後,後面的代碼不再阻塞,執行console.log(‘end test1‘);
· 執行下個宏任務,即執行console.log(‘setTimeout‘);
補充下有關宏任務和微任務的知識
宏任務和微任務都是隊列,宏任務有script、setTimeout、setInterval等,微任務有Promise.then catch finally、process.nextTick等,宏任務和微任務的關系如下:
先執行第一個宏任務,執行結束後,執行所有的微任務,然後執行下個宏任務。
參考:
1. https://segmentfault.com/a/1190000007535316
2. https://segmentfault.com/a/1190000017224799
3. https://www.cnblogs.com/wangziye/p/9566454.html
js async await