1. 程式人生 > >ES2017 中的非同步函式詳解(async function)

ES2017 中的非同步函式詳解(async function)

非同步函式中有兩個新的關鍵字asyncawait

async 就是非同步的意思
await 就是等的意思. 暫停函式的執行, 等待非同步任務完成.

宣告非同步函式


/*使用關鍵字 async 宣告非同步函式. 引數宣告和普通函式沒有任何的區別*/
async function testAsync(a, b){
    console.log(a, b);
    return "非同步";
}
/*呼叫非同步函式, 返回值是一個 Promise 物件*/
var promise = testAsync(10, 20);
console.log(promise);

說明:

  • 使用關鍵字 async

    宣告非同步函式

  • 非同步函式預設返回一個已決的promise.

  • 也可以在非同步函式中新增return "abc"語句, 則會把這個值封裝成 Promise.resolve("abc")

  • 如果想返回一個rejectPromise則可以在函式內部丟擲一個異常即可.

await

如果非同步函式內沒有出現await則上面的非同步函式和一個普通的函式沒有太大的區別.

如果有了await則會大大的不一樣.

await是等待的意思, 到底在等啥?

在等待一個非同步任務的完成. 一般是等待一個 Promise resolve. 當然可以等任何其他的值.

function resolve2Second
(x){
return new Promise(function (resolve, reject){ setTimeout(() => resolve(x), 2000); }) } async function add(){ var a = await resolve2Second(20); // 2 秒鐘之後 a為 20 var b = await resolve2Second(30); // 2 秒鐘之後 b為30 return a + b; // } add().then(function (value){ // 4s中之後, 返回的promsie 會變成已決狀態, 執行then中的函式
console.log(value); // 50 })

說明:

  • await 會等待, 等到Promise resolve之後, 他的運算的最終結果是resolve(值)中的值.

  • 有一點需要注意的時候, await只能在非同步函式內執行.

  • 呼叫async函式雖然有等待, 但是並不會導致阻塞, 因為他內部的所有阻塞都封裝在Promise物件中非同步執行.

非同步函式的優勢在哪裡

需求:
考慮有多個任務, 每個任務都依賴上一個任務的結果. 用setTimeout來模擬每個任何的耗時.

使用單純的Promise來完成

/*n表示耗時, n+1000傳給下個任務*/
function doSomething(n){
    return new Promise((resolve, reject) =>{
        setTimeout(() => resolve(n + 1000), n)
    })
}

function task1(n){
    console.log("任務1:" + n)
    return doSomething(n);
}

function task2(n){
    console.log("任務2:" + n)
    return doSomething(n);
}

function task3(n){
    console.log("任務3:" + n)
    return doSomething(n);
}

function doit(){
    task1(1000)
        .then(function (time2){
            return task2(time2);
        })
        .then(function (time3){
            return task3(time3);
        })
        .finally(function (){
            console.log("任務結束");
        })

}

doit();

使用 asyncawait

如果使用非同步函式配合await會發現程式碼像同步一樣舒服.

/*n表示耗時, n+1000傳給下個任務*/
function doSomething(n){
    return new Promise((resolve, reject) =>{
        setTimeout(() => resolve(n + 1000), n)
    })
}

function task1(n){
    console.log("任務1:" + n)
    return doSomething(n);
}

function task2(n){
    console.log("任務2:" + n)
    return doSomething(n);
}

function task3(n){
    console.log("任務3:" + n)
    return doSomething(n);
}

async function doit(){
    var time2 = await task1(1000) // 等待第一個任務 resolve
    var time3 = await task2(time2) // 等待第二個任務 resolve
    var result = await task3(time3)
    console.log("任務結束:" + result);
}
doit();