全手打原創,轉載請標明出處:http://www.javashuo.com/article/p-dpxcddwt-gr.html,多謝,=。=~html
拋出3個疑問:express
一、async是幹哈的?異步
二、await在等啥?async
三、await等到了又要幹哈?函數
先說說AsyncFunctionspa
AsyncFunction構造函數用來建立新的異步函數對象,JavaScript中每一個異步函數都是AsyncFunction的對象。線程
new AsyncFunction([arg1[, arg2[, ...argN]],] functionBody)
arg1, arg2, ... argN:函數參數名,一個或多個用逗號隔開的字符串;code
functionBody:一段字符串形式的 JavaScript 語句,這些語句組成了新函數的定義;htm
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) 中。
一、異步函數表達式
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 });
二、異步函數語句
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個疑問:
一、async是幹哈的?
定義異步函數(內部一般有異步操做),返回Promise對象(函數返回Promise→顯式返回return的Promise;函數返回非Promise→隱式返回Promise.resolve()包裝的return值;)
二、await在等啥?
只能放在async函數中,等待右側表達式結果(函數→結果=return值;字符串→結果=字符串;)
三、await等到了又要幹哈?
阻塞後面的代碼,先執行async外部的同步代碼,同步代碼執行完再回到async內部,拿到運算結果(表達式返回Promise→等待Promise對象fulfilled,再將resolve參數做爲表達式的運算結果;表達式返回非Promise→直接做爲表達式的運算結果;)
參考資料:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference