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"
}
]
]
}