1. 程式人生 > >ES7 - async 和 await

ES7 - async 和 await

async 是“非同步”的簡寫,而 await 可以認為是 async wait 的簡寫。
所以應該很好理解 async 用於宣告一個 函式 是非同步的,而 await 用於等待一個非同步函式執行完成
在函式前面加上async 關鍵字,來表示它是非同步的,那怎麼呼叫呢?async 函式也是函式,平時我們怎麼使用函式就怎麼使用它,直接加括號呼叫就可以了。

async function timeout() {
    return 'hello world'
}
console.log(timeout());  //列印async函式執行後是什麼值,這裡的輸出並不是它真的執行內部程式碼了
timeout().then( (data) => { console.log(data); }); console.log('雖然在後面,但是我先執行');

輸出結果:
Promise {: “hello world”}
雖然在後面,但是我先執行
hello world

async 函式返回的是一個Promise 物件,如果要獲取到Promise 返回值,我們應該用then 方法或者catch方法(當Promise物件返回resolved狀態之則呼叫then方法;async 函式內部丟擲錯誤返回rejected狀態則呼叫catch方法)。

async function
timeout(flag) { if (flag) { return 'hello world' } else { throw 'my god, failure' } } timeout(true).then(data => { console.log(data) }) timeout(false).catch(err => { console.log(err) })

輸出結果:
hello world
my god, failure

await 可以用於等待一個 async 函式的返回值——這也可以說是 await 在等 async 函式,但要清楚,它等的實際是一個返回值。注意到await 不僅僅用於等 Promise 物件,它可以等任意表達式的結果,所以,await 後面實際是可以接普通函式呼叫或者直接量的

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

async function test() {
    const v1 = await getSomething(); // await後面跟普通函式
    const v2 = await testAsync();    // await後面跟async函式
    console.log(v1);
    console.log(v2);
}

test();
//最後輸出:
// normal function
// async function

如果await等到的是一個 Promise 物件,等著 Promise 物件 resolve,然後得到 resolve 的值,作為 await 表示式的運算結果。await 就忙起來了,它會阻塞後面的程式碼。這裡的阻塞——就是 await 必須用在 async 函式中的原因。async 函式呼叫不會造成阻塞,它內部所有的阻塞都被封裝在一個 Promise 物件中非同步執行。

// 2s 之後返回雙倍的值
function doubleAfter2seconds(num) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2 * num)
        }, 2000);
    } )
    // return Promise.resolve(2 * num);
}

async function testResult() {
    let result = await doubleAfter2seconds(30);
    console.log(result);
}
testResult();  // 2s之後,控制檯輸出 60

————————————————————————————————————
使用 ES7 的 async/await 時報錯現象:
原因:這個regeneratorRuntime在瀏覽器上是不認識的,通過百度,需要安裝一個babel-plugin-transform-runtime外掛。
1、使用npm安裝
npm i --save-dev babel-plugin-transform-runtime
2、然後在 .babelrc 檔案中新增:

{
"plugins": [
	[
	    "transform-runtime",
	    {
	      "helpers": false,
	      "polyfill": false,
	      "regenerator": true,
	      "moduleName": "babel-runtime"
	    }
    ]
  ]
}