簡單理解JavaScript 的async/await

什麼是Async/Await?

  • async 函數 : 是 Generator 函數的語法糖
  • async函數返回一個 Promise 對象,可使用then方法添加回調函數。當函數執行的時候,一旦遇到await就會先返回,等到異步操做完成,再接着執行函數體內後面的語句。
  • async/await與Promise同樣,是非阻塞的
  • async函數返回的是 Promise 對象,能夠做爲await命令的參數

2、語法

一、返回 Promise 對象

async函數返回一個 Promise 對象。html

async函數內部return語句返回的值,會成爲then方法回調函數的參數。git

async function f() {
    return 'hello world';
}

f().then(v => console.log(v))
// "hello world"


async函數內部拋出錯誤,會致使返回的 Promise 對象變爲reject狀態。拋出的錯誤對象會被catch方法回調函數接收到github

async function f() {
    throw new Error('出錯了');
}

f().then(
    v => console.log(v),
    e => console.log(e)
)
// Error: 出錯了


二、Promise對象的狀態變化

只有async函數內部的異步操做執行完,纔會執行then方法指定的回調函數。promise

async function getTitle(url) {
    let response = await fetch(url);
    let html = await response.text();
    return html.match(/<title>([\s\S]+)<\/title>/i)[1];
}
getTitle('https://tc39.github.io/ecma262/').then(console.log)
// "ECMAScript 2017 Language Specification"

三、await命令

正常狀況下,await命令後面是一個 Promise 對象。若是不是,會被轉成一個當即resolve的 Promise 對象。異步

await命令後面的 Promise 對象若是變爲reject狀態,則reject的參數會被catch方法的回調函數接收到。async

只要一個await語句後面的 Promise 變爲reject,那麼整個async函數都會中斷執行函數

async function f() {
    await Promise.reject('出錯了');
    await Promise.resolve('hello world'); // 不會執行
}


有時,咱們但願即便前一個異步操做失敗,也不要中斷後面的異步操做。這時能夠將第一個await放在try...catch結構裏面,這樣無論這個異步操做是否成功,第二個await都會執行。fetch

async function f() {
    try {
        await Promise.reject('出錯了');
    } catch(e) {
    }
    return await Promise.resolve('hello world');
}

f()
.then(v => console.log(v))
// hello world


另外一種方法是await後面的 Promise 對象再跟一個catch方法,處理前面可能出現的錯誤。url

async function f() {
    await Promise.reject('出錯了')
    .catch(e => console.log(e));
    return await Promise.resolve('hello world');
}

f()
.then(v => console.log(v))
// 出錯了
// hello world


四、錯誤處理

若是await後面的異步操做出錯,那麼等同於async函數返回的 Promise 對象被reject。spa

防止出錯的方法,將其放在try...catch代碼塊之中。

async function f() {
    try {
        await new Promise(function (resolve, reject) {
            throw new Error('出錯了');
        });
    } catch(e) {
    }
    return await('hello world');
}
若是有多個await命令,能夠統一放在try...catch結構中。

async function main() {
    try {
        const val1 = await firstStep();
        const val2 = await secondStep(val1);
        const val3 = await thirdStep(val1, val2);
        console.log('Final: ', val3);
    }
    catch (err) {
        console.error(err);
    }
}

總結

函數前的 async 關鍵字有兩個做用:

  1. 老是返回 promise。
  2. 容許在其中使用 await。

在 promise 以前的 await 關鍵字,使 JavaScript 等待 promise 被處理,而後:

  1. 若是有 error,就會產生異常,就像在那個地方調用了 throw error同樣。
  2. 不然,就會返回值,咱們能夠給它分配一個值。
相關文章
相關標籤/搜索