理解ES7中的async/awaitpromise
優點是:就是解決多層異步回調的嵌套異步
從字面上理解 async/await, async是 "異步"的含義,await能夠認爲是 async wait的簡寫,所以能夠理解 async 用於聲明一個function是異步的,而await用於等待一個異步方法執行完成返回的值(返回值能夠是一個Promise對象或普通返回的值)。
注意:await 只能出如今 async函數中。async
1-1 async的做用?
首先來理解async函數是怎麼處理返回值的,咱們之前寫代碼都是經過return語句返回咱們想要的值,可是async與return有什麼區別呢? 下面咱們看以下代碼:函數
async function testAsync() { return 'hello world'; } const result = testAsync(); console.log(result); // 打印出來看到 返回一個promise對象
如上代碼,咱們輸出的是一個Promise對象。所以 async返回的是一個Promise對象,所以咱們可使用 then()鏈來處理這個Promise對象。像以下代碼:優化
async function testAsync() { return 'hello world'; } const result = testAsync(); result.then(v => { console.log(v); // 輸出 hello world });
可是若是 async函數沒有返回值的話,那麼就會返回 undefined; 以下代碼:spa
async function testAsync() { return; } const result = testAsync(); result.then(v => { console.log(v); // 輸出 undefined });
1-2 await的做用?
從語義上說,await是在等待一個async函數完成的,async函數返回的是一個Promise對象,await等待的是一個表達式,這個表達式的計算結果是Promise對象或其餘值。
async函數返回一個Promise對象,await做用是用於等待一個async函數的返回值。
await函數後面能夠接普通函數調用或直接量,請看以下代碼:code
function getSomething() { return 'something'; } async function testAsync() { return Promise.resolve('hello'); } async function test () { const v1 = await getSomething(); const v2 = await testAsync(); console.log(v1); // something console.log(v2); // hello } test();
注意:await 是等待async函數返回的Promise對象或其餘值,await是一個運算符,用於組成表達式, 若是等待的是一個Promise對象,await會阻塞後面的代碼(async調用不會形成堵塞,它內部全部的堵塞
都被封裝在一個Promise對象中異步執行),等待Promise對象的resolve,而後獲得resolve的值,做爲await表達式的運輸結果。對象
1-3 async/await 的一塊兒使用的做用及優點在哪?
咱們先不用 async/await, 來看看使用setTimeout模擬異步操做以下代碼:blog
var test = function(time) { return new Promise((resolve, reject) => { setTimeout(function(){ resolve('hello world'); }, time) }); }; test(1000).then((v) => { console.log(v); });
若是改用 async/await 代碼以下:get
var testAsync = function(time) { return new Promise((resolve, reject) => { setTimeout(function(){ resolve('hello world'); }, time) }); }; async function test(time) { const v = await testAsync(time); console.log(v); // hello world } test(1000);
看上面的代碼,反而會以爲 使用 async/await 代碼變得多一點,複雜一點,可是結果貌似都同樣,那麼使用 async/await的優點在哪?
1-4 async/await的優點在於處理then鏈
單一的Promise鏈貌似不能發現 async/await的優點,可是若是須要處理多個Promise組成的then鏈的時候,優點能夠看出來,由於Promise是經過then鏈來解決多層回調的問題,如今咱們又可使用
async/await來進一步優化,他們的優勢就是解決多層異步回調的嵌套。
假設咱們如今有一個需求是,分多個步驟完成,每一個步驟都是異步的,而且後面的異步都須要依賴於上一個異步回調返回的數據,進行往下傳遞。咱們先用 setTimeout來模擬異步操做。
function useTimeout (t) { return new Promise((resolve, reject) => { setTimeout(()=> { resolve(t+100) }, t); }); } function step1(t) { console.log(`step1 with ${t}`); // step1 with 300 return useTimeout(t); } function step2(t) { console.log(`step2 with ${t}`); // step2 with 400 return useTimeout(t); } function step3(t) { console.log(`step3 with ${t}`); // step3 with 500 return useTimeout(t); } function test() { const time1 = 300; step1(time1) .then(time2 => step2(time2)) .then(time3 => step3(time3)) .then(res => { console.log(`result is ${res}`); // result is 600 }) } test();
若是咱們使用 async/await來實現,代碼變爲以下:
function useTimeout (t) { return new Promise((resolve, reject) => { setTimeout(()=> { resolve(t+100) }, t); }); } function step1(t) { console.log(`step1 with ${t}`); // step1 with 300 return useTimeout(t); } function step2(t) { console.log(`step2 with ${t}`); // step2 with 400 return useTimeout(t); } function step3(t) { console.log(`step3 with ${t}`); // step3 with 500 return useTimeout(t); } async function test() { const time1 = 300; const time2 = await step1(time1); const time3 = await step2(time2); const result = await step3(time3); console.log(`result is ${result}`); } test();
上面咱們能夠看到 使用async/await 代碼看起來都是同步的,等第一步完成後,再執行第二步,依次類推..... 而且不須要更多的回調函數嵌套。
下面咱們再來看下咱們以前講的,後面的步驟須要上一個步驟的結果傳遞進去,使用async/await的優點可能更明顯。
以下代碼:
function useTimeout (t) { return new Promise((resolve, reject) => { setTimeout(()=> { resolve(t+100) }, t); }); } function step1(t1) { console.log(`step1 with ${t1}`); // step1 with 300 return useTimeout(t1); } function step2(t1, t2) { console.log(`step2 with ${t1} and ${t2}`); // step2 with 300 and 400 return useTimeout(t1+t2); } function step3(t1, t2, t3) { console.log(`step3 with ${t1} and ${t2} and ${t3}`); // step3 with 300 and 400 and 800 return useTimeout(t1+t2+t3); } async function test() { const time1 = 300; const time2 = await step1(time1); const time3 = await step2(time1, time2); const result = await step3(time1, time2, time3); console.log(`result is ${result}`); // result is 1600 } test();
1-5 捕捉錯誤
咱們可使用 try catch 來捕獲錯誤,以下代碼:
var sleep = function (time) { return new Promise((resolve, reject) => { setTimeout(function() { // 出錯了, 返回 error reject('error'); }, time); }) }; var start = async function() { try { console.log('start'); await sleep(3000); // 返回一個錯誤 // 下面代碼不會被執行 console.log('end'); } catch (err) { console.log(err); // 捕捉錯誤 error } }; start();