1. 程式人生 > 其它 >async awit 非同步呼叫的理解及應用

async awit 非同步呼叫的理解及應用

技術標籤:Javascript

async awit 非同步呼叫的理解及應用

async 是“非同步”的簡寫,而 await 可以認為是 async wait 的簡寫。所以應該很好理解 async 用於申明一個 function 是非同步的,而 await 用於等待一個非同步方法執行完成。

1.1. async 起什麼作用
async 函式,輸出的是一個 Promise 物件。(從文件中也可以得到這個資訊),async 函式(包含函式語句、函式表示式、Lambda表示式)會返回一個 Promise 物件,如果在函式中 return 一個直接量,async 會把這個直接量通過 Promise.resolve() 封裝成 Promise 物件。

async function testAsync() {
    return "hello async";
}

const result = testAsync();
console.log(result);
  1. async/await 幹了啥
    2.1 比較
    示例:
    //用 setTimeout 模擬耗時的非同步操作
function takeLongTime() {
    return new Promise(resolve => {
        setTimeout(() => resolve("long_time_value"), 1000
); }); } takeLongTime().then(v => { console.log("got", v); });

//如果改用 async/await 呢,會是這樣

function takeLongTime() {
    return new Promise(resolve => {
        setTimeout(() => resolve("long_time_value"), 1000);
    });
}

async function test() {
    const v = await takeLongTime
(); console.log(v); } test();

2.2. async/await 的優勢在於處理 then 鏈
單一的 Promise 鏈並不能發現 async/await 的優勢,但是,如果需要處理由多個 Promise 組成的 then 鏈的時候,優勢就能體現出來了(很有意思,Promise 通過 then 鏈來解決多層回撥的問題,現在又用 async/await 來進一步優化它)。

假設一個業務,分多個步驟完成,每個步驟都是非同步的,而且依賴於上一個步驟的結果。我們仍然用 setTimeout 來模擬非同步操作:

/**
 * 傳入引數 n,表示這個函式執行的時間(毫秒)
 * 執行的結果是 n + 200,這個值將用於下一步驟
 */
function takeLongTime(n) {
    return new Promise(resolve => {
        setTimeout(() => resolve(n + 200), n);
    });
}

function step1(n) {
    console.log(`step1 with ${n}`);
    return takeLongTime(n);
}

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

function step3(n) {
    console.log(`step3 with ${n}`);
    return takeLongTime(n);
}

現在用 Promise 方式來實現這三個步驟的處理

function doIt() {
    console.time("doIt");
    const time1 = 300;
    step1(time1)
        .then(time2 => step2(time2))
        .then(time3 => step3(time3))
        .then(result => {
            console.log(`result is ${result}`);
            console.timeEnd("doIt");
        });
}

doIt();

// c:\var\test>node --harmony_async_await .
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900
// doIt: 1507.251ms

輸出結果 result 是 step3() 的引數 700 + 200 = 900。doIt() 順序執行了三個步驟,一共用了 300 + 500 + 700 = 1500 毫秒,和 console.time()/console.timeEnd() 計算的結果一致。

如果用 async/await 來實現呢,會是這樣

async function doIt() {
    console.time("doIt");
    const time1 = 300;
    const time2 = await step1(time1);
    const time3 = await step2(time2);
    const result = await step3(time3);
    console.log(`result is ${result}`);
    console.timeEnd("doIt");
}

doIt();

結果和之前的 Promise 實現是一樣的,但是這個程式碼看起來應該清晰得多,幾乎跟同步程式碼一樣

可參考:
阮一峰es6
https://segmentfault.com/a/1190000007535316