async await
是異步編程的另外一種解決方案es6
async
函數是對Generator
函數的改進編程
async
函數返回一個 Promise
實例,能夠使用then
方法(爲返回的Promise實例)添加回調函數。當函數執行的時候,一旦遇到await
就會先返回,等到異步操做完成,再接着執行函數體內後面的語句。服務器
例 1:異步
上面代碼是一個獲取股票報價的函數,函數前面的async
關鍵字,代表該函數內部有異步操做。調用該函數時,會當即返回一個Promise
實例。async
async
函數內部return
語句返回的值,會成爲then
方法回調函數的參數。異步編程
async
函數返回的 Promise
對象,必須等到內部全部await
命令後面的 Promise
對象執行完,纔會發生狀態改變,除非遇到return語句或者拋出錯誤。也就是說,只有async
函數內部的異步操做執行完,纔會執行then
方法指定的回調函數。函數
正常狀況下,await
命令後面是一個Promise
實例,若是不是,會被轉成一個當即resolve
的Promise
實例。spa
async function f() { return await 123; } f().then(v => console.log(v))
等價於code
async function f() { return await new Promise(function(resolve){ resolve(123) }) } f().then(v => console.log(v))
等價於對象
async function f() { return await Promise.resolve('123') } f().then(v => console.log(v))
await語句的返回值是await命令後面Promise實例的結果(異步處理的結果)
function getResult() { return new Promise((resolve) => { resolve('result: 1000') // resolve()方法的參數就是異步處理的結果 }); } async function asyncPrint() { const result = await getResult() // 將異步處理的結果賦值給result return result } asyncPrint().then( (result) => { console.log(result) } ) //'result: 1000'
若是await
後面的異步操做出錯,那麼等同於async
函數返回的 Promise
對象被reject
。
async function f() { await new Promise(function (resolve, reject) { throw new Error('出錯了'); }); } f() .then(v => console.log(v)) .catch(e => console.log(e)) // Error:出錯了
防止出錯的方法,也是將其放在try...catch代碼塊之中。
async function f() { try { await new Promise(function (resolve, reject) { throw new Error('出錯了'); }); } catch(e) { } return await('hello world'); }
若是await
後面的異步操做出錯,那麼等同於async
函數返回的 Promise
對象被reject
,因此最好把await
命令放在try...catch
代碼塊中。
async function myFunction() { try { await somethingThatReturnsAPromise(); } catch (err) { console.log(err); } } // 另外一種寫法 async function myFunction() { await somethingThatReturnsAPromise() .catch(function (err) { console.log(err); }); }
多個await
命令後面的異步操做,若是不存在繼發關係,最好讓它們同時觸發。
let foo = await getFoo(); let bar = await getBar();
上面代碼中,getFoo
和getBar
是兩個獨立的異步操做(即互不依賴),被寫成繼發關係(只有執行完getFoo操做,才能去執行getBar操做)。這樣比較耗時,由於只有getFoo
完成之後,纔會執行getBar
,徹底能夠讓它們同時觸發。
解釋:這裏的getFoo
和getBar
方法會返回兩個Promise
實例(假設是發起Ajax請求,請求foo和bar的內容),只有執行了方法,對應的操做纔會執行,若是寫成上面的形式,就會致使執行完getFoo
的操做後(等待收到服務器的響應後),才能執行getBar
的操做,這樣就成了同步,比較耗時,所以能夠將上面的寫法修改,使得在等待getFoo
執行完的時間內(在等待服務器響應的期間)去執行執行getBar
記住:當函數執行的時候,一旦遇到await就會先返回,等到異步操做完成,再接着執行函數體內後面的語句。
// 寫法一 let [foo, bar] = await Promise.all([getFoo(), getBar()]); // 寫法二 let fooPromise = getFoo(); let barPromise = getBar(); let foo = await fooPromise; let bar = await barPromise;
上面兩種寫法,getFoo
和getBar
都是同時觸發,這樣就會縮短程序的執行時間。