全手打原創,轉載請標明出處:https://www.cnblogs.com/dreamsqin/p/11533174.html,多謝,=。=~
拋出3個疑問:
1、async是干哈的?
2、await在等啥?
3、await等到了又要干哈?
先說說AsyncFunction
AsyncFunction構造函數用來創建新的異步函數對象,JavaScript中每個異步函數都是AsyncFunction的對象。
new AsyncFunction([arg1[, arg2[, ...argN]],] functionBody)
arg1, arg2, ... argN:函數參數名,一個或多個用逗號隔開的字符串;
functionBody:一段字符串形式的 JavaScript 語句,這些語句組成了新函數的定義;
function resolveAfter2Seconds(x) { return new Promise(resolve => { setTimeout(() => { resolve(x); }, 2000); }); } var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor; var a = new AsyncFunction('a', 'b', 'return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b);'); a(10, 20).then(v => { console.log(v); // 4 秒后打印 30 });
注:AsyncFunction非全局對象,所以需要通過 Object.getPrototypeOf(async function(){}).constructor 獲取
先說明AsyncFunction的原因是執行 AsyncFunction 構造函數時,可以創建一個異步函數對象。但是這種方式不如先用異步函數表達式(也就是async function)定義一個異步函數,然后再調用它來創建異步函數對象來的高效,因為第二種方式中異步函數是與其他代碼一起被解釋器解析的,而第一種方式的函數體是單獨解析的。可以跟下面async的例子對比查看。
接着上async定義+語法
帶async關鍵字的函數,它使得你的函數返回值必定是Promise對象
不明白的可以在console中敲一下下面的代碼:
async關鍵字使用分為異步函數表達式和異步函數語句,兩者非常相似,語法也基本相同。它們之間的主要區別在於異步函數表達式可以省略函數名稱來創建一個匿名函數。另外,異步函數表達式還可以用在 IIFE (立即執行函數表達式,Immediately Invoked Function Expression) 中。
1、異步函數表達式
async function [name]([param1[, param2[, ..., paramN]]]) { statements }
name:此異步函數的名稱,可省略。如果省略則這個函數將成為匿名函數。該名稱僅可在本函數中使用。
function resolveAfter2Seconds(x) { return new Promise(resolve => { setTimeout(() => { resolve(x); }, 2000); }); }; // async function expression assigned to a variable var add1 = async function(x) { var a = await resolveAfter2Seconds(20); var b = await resolveAfter2Seconds(30); return x + a + b; } add1(10).then(v => { console.log(v); // 4 秒后打印 60 }); (async function(x) { // async function expression used as an IIFE var p_a = resolveAfter2Seconds(20); var p_b = resolveAfter2Seconds(30); return x + await p_a + await p_b; })(10).then(v => { console.log(v); // 2 秒后打印 60 });
2、異步函數語句
async function name([param[, param[, ... param]]]) { statements }
name:函數名稱
function resolveAfter2Seconds() { return new Promise(resolve => { setTimeout(() => { resolve('resolved'); }, 2000); }); } async function asyncCall() { console.log('calling'); var result = await resolveAfter2Seconds(); console.log(result); // expected output: 'resolved' } asyncCall();
執行順序:
(1)異步函數可以包含await指令,該指令會暫停原異步函數的執行,並等待右側Promise返回結果;
(2)當異步函數暫停時,await右側調用的函數會繼續執行(收到異步函數返回的隱式Promise);
然后上await定義+語法
用於等待右側表達式的結果(先執行右側表達式再讓出線程阻塞代碼,若右側為同步直接執行,若為異步會等待外部同步代碼執行完畢)。它只能在異步函數 async function 中使用。
[return_value] = await expression
Expression:一個 Promise 對象或者任何要等待的值;
return_value:返回 Promise 對象的處理結果;如果等待的不是 Promise 對象,則返回該值本身;
執行順序:
(1)await 表達式會暫停當前 async function 的執行,等待 Promise 處理完成;
(2)若 Promise 正常處理(Resolved,又稱Fulfilled),其回調resolve函數的參數作為 await 表達式的值,繼續執行 async function;
(3)若 Promise 處理異常(Rejected),await 表達式會把 Promise 的異常原因拋出;
解決開頭的3個疑問:
1、async是干哈的?
定義異步函數(內部通常有異步操作),返回Promise對象(函數返回Promise→顯式返回return的Promise;函數返回非Promise→隱式返回Promise.resolve()包裝的return值;)
2、await在等啥?
只能放在async函數中,等待右側表達式結果(函數→結果=return值;字符串→結果=字符串;)
3、await等到了又要干哈?
阻塞后面的代碼,先執行async外部的同步代碼,同步代碼執行完再回到async內部,拿到運算結果(表達式返回Promise→等待Promise對象fulfilled,再將resolve參數作為表達式的運算結果;表達式返回非Promise→直接作為表達式的運算結果;)
參考資料:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference