理解async/await

前言

js有不少異步處理的解決方案,而async/await就是其中的一種,最近有在學習和運用koa,在服務端中,不多用到promise,而是選擇了更加優雅的async/await。固然,一種新方案的出現,咱們不光須要學會怎麼寫,也要學會他的原理。express

async/await起到什麼做用

async/await從字面意思上很好理解,async是異步的意思,await有等待的意思,而二者的用法上也是如此。async用於申明一個function是異步的,而await 用於等待一個異步方法執行完成。promise

async

async的語法很簡單,就是在函數開頭加一個關鍵字,示例以下:bash

async function f() {
    return 1;
}
複製代碼

async關鍵字的意思很簡單,就是函數返回的是一個promise。koa

async function f() {
    return 1;
}
f().then((res) => {
    console.log(res)
}) // 1
複製代碼

async函數會返回一個promise對象,若是function中返回的是一個值,async直接會用Promise.resolve()包裹一下返回。異步

await

關鍵詞await是等待的意思,那麼他在等什麼呢? 在MDN上寫的是:async

[return_value] = await expression;
複製代碼

等的是一個表達式,那麼表達式,能夠是一個常量,變量,promise,函數等。函數

function getSomething() {
    return "something";
}

async function testAsync() {
    return Promise.resolve("hello async");
}

async function test() {
    const v1 = await getSomething();
    const v2 = await testAsync();
    console.log(v1, v2);
}

test(); // something hello async
複製代碼
  • 爲何await關鍵詞只能在async函數中用

await操做符等的是一個返回的結果,那麼若是是同步的狀況,那就直接返回了。學習

那若是是異步的狀況呢,異步的狀況下,await會阻塞整一個流程,直到結果返回以後,纔會繼續下面的代碼。ui

阻塞代碼是一個很可怕的事情,而async函數,會被包在一個promise中,異步去執行。因此await只能在async函數中使用,若是在正常程序中使用,會形成整個程序阻塞,得不償失。 spa

async/await中錯誤處理

promise並非只有一種resolve,還有一種reject的狀況。而await只會等待一個結果,那麼發生錯誤了該怎麼處理呢?

  • 用try-catch來作錯誤捕捉
async function myFunction() {
  try {
    await Promise.reject('1');
  } catch (err) {
    console.log(err);
  }
}
myFunction(); // 1
複製代碼
  • 用promise的catch來作錯誤捕捉
async function myFunction() {
    await Promise.reject('1').catch((err) => {
        console.log(err);
    });
}
myFunction(); // 1
複製代碼

async/await和promise的區別

promise最大的問題就是在於業務複雜以後,then內部的邏輯也變得複雜,或者循環的異步嵌套場景等,會寫出來不那麼優美。

我隨意列舉一個嵌套的例子,而後分別用async/awaitpromise,你就能感覺到二者之間的差距:

function takeLongTime(n) {
    return new Promise(resolve => {
        setTimeout(() => resolve(n), n);
    });
}
function step1(n) {
    console.log(`step1 with ${n}`);
    return takeLongTime(n);
}

function step2(m, n) {
    console.log(`step2 with ${m} and ${n}`);
    return takeLongTime(m + n);
}

function step3(k, m, n) {
    console.log(`step3 with ${k}, ${m} and ${n}`);
    return takeLongTime(k + m + n);
}
複製代碼

takeLongTime起到的做用就是延時以後給出延時的數據。

step1表明第一步延時了多久。

step2表明第一步和第二部總共延時了多久。

step3表明第一步、第二步和第三步一共延時了多久。

  • promise版本
function doIt() {
    console.time("doIt");
    const time1 = 300;
    step1(time1)
        .then(time2 => {
            return step2(time1, time2)
                .then(time3 => [time1, time2, time3]);
        })
        .then(times => {
            const [time1, time2, time3] = times;
            return step3(time1, time2, time3);
        })
        .then(result => {
            console.log(`result is ${result}`);
            console.timeEnd("doIt");
        });
}

doIt();
複製代碼
  • async/await版本
async function doIt() {
    console.time("doIt");
    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}`);
    console.timeEnd("doIt");
}

doIt();
複製代碼

在這種複雜邏輯中,咱們就能發現async/await確實比then鏈有優點。

總結

async/await是一種異步的解決方案,而koa中支持這一特性,因此,在基於koa來寫服務端代碼的時候,這種語法糖不可避免,學習和運用它是咱們的必修課。

相關文章
相關標籤/搜索