2021-9-24 前端達人
這篇文章多看幾遍加深理解
async function 聲明定義了一個異步函數,它返回一個AsyncFunction對象。異步函數 是指通過 事件循環(event loop) 異步執行的函數,通過返回一個隱式的 Promise 作為其結果。使用異步函數的代碼的語法和結構更像使用標準同步功能。(The async function declaration defines an asynchronous function, which returns an AsyncFunction object. An asynchronous function is a function which operates asynchronously via the event loop, using an implicit Promise to return its result. But the syntax and structure of your code using async functions is much more like using standard synchronous functions.
)
async function name([param[, param[, ... param]]]) { statements }
參數:
返回值:返回一個promise
對象,將返回異步函數返回的值(如果異步函數是resolved則返回resolved的值;如果拋出異常,則rejected從異步函數中拋出的異常)。(A Promise which will be resolved with the value returned by the async function, or rejected with an uncaught exception thrown from within the async function.)
異步函數可以包含await
表達式,該表達式暫停異步函數的執行 并等待 Promise的執行結果返回,結果返回后就恢復異步函數的執行。
await 關鍵字只在異步函數(async functions)內有效。如果在異步函數外使用它,會拋出語法錯誤。
當異步函數暫停時,它調用的函數仍會繼續執行。
舉例一:
function resolveAfter5Seconds() { return new Promise(resolve => { setTimeout(() => { resolve('resolved'); }, 5000); }); } async function asyncCall() { console.log('calling'); let result = await resolveAfter5Seconds(); console.log(result); // 5s之后輸出結果 } asyncCall(); //返回的是一個promise對象 // console.log(asyncCall()); // Promise { <pending> }
運行效果:
舉例二:
let resolveAfter6Second = function () { console.log('start slow promise'); return new Promise(resolve => { setTimeout(() => { resolve('slow'); console.log('slow promise is done'); }, 6000); }) } let resolveAfter4Second = function () { console.log('start fast promise'); return new Promise(resolve => { setTimeout(() => { resolve('fast'); console.log('fast promise is done'); }, 4000); }) } let sequentialStart = async function () { console.log('sequential start'); const slow = await resolveAfter6Second(); console.log(slow); const fast = await resolveAfter4Second(); console.log(fast); } sequentialStart() //立即輸出 // sequential start // start slow promise //再過6秒后輸出 // slow promise is done // slow // start fast promise //再過4秒后輸出 // fast promise is done // fast
運行效果:
換一種await
的寫法,結果完全不同:兩個計時器被同時創建
let resolveAfter6Seconds = function () { console.log('start slow promise'); return new Promise(resolve => { setTimeout(() => { resolve('slow'); console.log('slow promise is done'); }, 6000); }) } let resolveAfter4Seconds = function () { console.log('start fast promise'); return new Promise(resolve => { setTimeout(() => { resolve('fast'); console.log('fast promise is done'); }, 4000); }) } let concurrentStart = async function () { console.log('concurrent start'); let slow = resolveAfter6Seconds(); let fast = resolveAfter4Seconds(); console.log(await slow); console.log(await fast); } setTimeout(() => { concurrentStart(); }, 2000); //2秒后執行 // concurrent start // start slow promise // start fast promise //再過4秒后執行 // fast promise is done //再過2秒后執行 // slow promise is done // slow // fast
運行效果:
在 concurrentStart 中,兩個計時器被同時創建,接著執行await。等待的是 promise的resolve回調,resolve后面的代碼( console.log(‘fast promise is done’);)會繼續執行。
這兩個計時器同時運行。但是 await 仍舊是順序執行的,第二個 await 還是得等待第一個執行完。在這個例子中,這使得先運行結束的輸出出現在最慢的輸出之后。
也可以把 concurrentStart 改寫成如下,運行效果一樣:
let resolveAfter6Seconds = function () { console.log('start slow promise'); return new Promise(resolve => { setTimeout(() => { resolve('slow'); console.log('slow promise is done'); }, 6000); }) } let resolveAfter4Seconds = function () { console.log('start fast promise'); return new Promise(resolve => { setTimeout(() => { resolve('fast'); console.log('fast promise is done'); }, 4000); }) } let concurrentPromise = async function () { console.log('concurrent start'); return Promise.all([resolveAfter6Seconds(), resolveAfter4Seconds()]).then((messages) => { console.log(messages[0]); // slow console.log(messages[1]); // fast }); } setTimeout(() => { concurrentPromise(); }, 2000); //2秒后輸出 // concurrent start // start slow promise // start fast promise //再過6秒后輸出 // fast promise is done //再過2秒后輸出 // slow promise is done // slow // fast
并行執行兩個或更多的任務,如下例所示:
let resolveAfter6Seconds = function () { console.log('start slow promise'); return new Promise(resolve => { setTimeout(() => { resolve('slow'); console.log('slow promise is done'); }, 6000); }) } let resolveAfter4Seconds = function () { console.log('start fast promise'); return new Promise(resolve => { setTimeout(() => { resolve('fast'); console.log('fast promise is done'); }, 4000); }) } let parallel = async function () { console.log('start paralel'); await Promise.all([ (async () => console.log(await resolveAfter6Seconds()))(), (async () => console.log(await resolveAfter4Seconds()))() ]); } setTimeout(parallel, 2000); //2秒后輸出 // start paralel // start slow promise // start fast promise //再過4秒后輸出 // fast promise is done // fast //再過2秒后輸出 // slow promise is done // slow
運行效果:
如果希望并行執行兩個或更多的任務,你必須像在parallel中一樣使用await Promise.all([job1(), job2()])
也可以把parallel改寫成如下,運行效果一樣:
let resolveAfter6Seconds = function(){ console.log('start slow promise'); return new Promise(resolve => { setTimeout(() => { resolve('slow'); console.log('slow promise is done'); }, 6000); }); } let resolveAfter4Seconds = function(){ console.log('start fast promise'); return new Promise(resolve =>{ setTimeout(() => { resolve('fast'); console.log('fast promise is done'); }, 4000); }) } let parallelPromise = function(){ console.log('parallelPromise start'); resolveAfter6Seconds().then(msg => console.log(msg)); resolveAfter4Seconds().then(msg => console.log(msg)); } setTimeout(() => { parallelPromise(); }, 2000); //2秒后輸出 // parallelPromise start // start slow promise // start fast promise //再過4秒后輸出 // fast promise is done // fast //再過2秒后輸出 // slow promise is done // slow
async/await和Promise#then對比以及錯誤處理:
大多數異步函數(async functions )也可以使用 Promises函數 編寫。然而,當涉及到錯誤處理時,異步函數不太容易出錯。
上面例子中的concurrentStart函數和concurrentPromise函數在功能上都是等效的。在concurrentStart函數中,如果任一awaited調用失敗,它將自動捕獲異常,異步函數執行中斷,并通過隱式返回Promise將錯誤傳遞給調用者。
在Promise例子中這種情況同樣會發生,函數必須負責返回一個捕獲函數完成的Promise。在concurrentPromise函數中,這意味著它從Promise.all([]).then()中返回一個Promise。事實上,在此示例的先前版本忘記了這樣做!
但是,async函數仍有可能然可能錯誤地忽略錯誤。
以parallel異步函數為例。 如果它沒有等待await(或 return)Promise.all([])調用的結果,則不會傳播任何錯誤。
雖然parallelPromise函數示例看起來很簡單,但它根本不會處理錯誤! 這樣做需要一個類似于return Promise.all([])處理方式。(詳見)
返回 Promise的 API 將會產生一個 promise 鏈,它將函數分解成許多部分。例如下面的代碼:
function getProcessedData(url) { return downloadData(url)// returns a promise .catch(e => { return downloadFallbackData(url);// returns a promise }) .then(v => { return processDataInWorker(v);// returns a promise }) }
可以重寫為單個async函數:
async function getProcessedData(url) { let v; try { v = await downloadData(url); } catch (e) { v = await downloadFallbackData(); } return processDataInWorker(v); }
在上述示例中,return 語句中沒有 await 操作符,因為 async function 的返回值將被隱式地傳遞給 Promise.resolve。
return await promiseValue;
與 return promiseValue;
的比較
返回值隱式的傳遞給Promise.resolve
,并不意味著return await promiseValue;
,只是在功能上等同于返回return promiseValue;
。
重寫的上面代碼,在processDataInWorker拋出異常時返回null:
async function getProcessedData(url) { let v; try { v = await downloadData(url); } catch(e) { v = await downloadFallbackData(url); } try { return await processDataInWorker(v); // 注意 `return await` 和單獨 `return` 的比較 } catch (e) { return null; } }
簡單地寫上return processDataInworker(v);將導致在processDataInWorker(v)出錯時function返回值為Promise而不是返回null。
return foo;
和return await foo;
有一些細微的差異:
return foo;
不管foo是promise還是rejects都將會直接返回foo。相反地,如果foo是一個Promise,return await foo;將等待foo執行(resolve)或拒絕(reject),如果是拒絕,將會在返回前拋出異常。
分享此文一切功德,皆悉回向給文章原作者及眾讀者.
轉自:csdn
免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。
藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務
藍藍設計的小編 http://www.syprn.cn