非同步神器--async
阿新 • • 發佈:2019-01-01
一、含義
學過ES6的同學大概都熟悉Generator函式,那麼async可以說是Generator的語法糖,它讓非同步操作變得更加方便。
二、語法特點
const asyncDemo = async function () {
await fn();
await fn2();
await fn3();
}
asyncDemo();
可以看出async函式在宣告的時候要加上async表示這個函式內有非同步操作,函式體內每一個await表示跟在其後面的表示式需要等待結果,在這裡我們可以進行非同步操作。await後面可以是Promise物件和原始型別的值(但這是等同於同步操作)
值得一提的是async函式可以像普通函式一樣直接呼叫,例如上面的asyncDemo(),這和Generator就不一樣了。而且async函式返回的是Promise物件,這樣的話我們就可以使用then方法指定下一步的操作。由於async
函式返回的 Promise 物件,必須等到內部所有await
命令後面的 Promise 物件執行完,才會發生狀態改變,除非遇到return
語句或者丟擲錯誤。也就是說,只有async
函式內部的非同步操作執行完,才會執行then
方法指定的回撥函式。
下面是一個例子:
async function f() { await Promise.reject('出錯了'); await Promise.resolve('hello world'); // 不會執行 } f() .then(v => console.log(v)) .catch(e => console.log(e)) // 出錯了
可以看到當async函式在遇到錯誤時便會中斷接下來的非同步操作,但是有時候我們不希望在出現錯誤時中斷程式,這個時候我們就可以使用try...catch結構了。如下:
async function f() {
try {
await Promise.reject('出錯了');
} catch(e) {
}
return await Promise.resolve('hello world');
}
f()
.then(v => console.log(v))
// hello world
三、使用形式
// 函式宣告 async function foo() {} // 函式表示式 const foo = async function () {}; // 物件的方法 let obj = { async foo() {} }; obj.foo().then(...) // Class 的方法 class Storage { constructor() { this.cachePromise = caches.open('avatars'); } async getAvatar(name) { const cache = await this.cachePromise; return cache.match(`/avatars/${name}.jpg`); } } const storage = new Storage(); storage.getAvatar('jake').then(…); // 箭頭函式 const foo = async () => {};
四、async的小demo
讓ajax請求按順序執行
const timeout = ms => new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, ms);
});
//假設ajax1,ajax2,ajax3是我們所需要要ajax請求
const ajax1 = () => timeout(2000).then(() => {
console.log('1');
return 1;
});
const ajax2 = () => timeout(1000).then(() => {
console.log('2');
return 2;
});
const ajax3 = () => timeout(2000).then(() => {
console.log('3');
return 3;
});
const ajaxRequests = ajaxArray => {
var data = [];
async function test() {
for (let request of ajaxArray){
try{
let val = await request();
data.push(val);
}catch(err){
console.log('error');
}
}
}
async function result(){
await test();
return data;
}
return result();
};
ajaxRequests([ajax1, ajax2, ajax3]).then(data => {
console.log('done');
console.log(data); // data 為 [1, 2, 3]
});
當然這個是針對互相依賴的非同步操作,因為只有ajax1請求完之後才會執行ajax2....,如果是互不依賴的最好讓他們同時觸發這樣比較省時(可以使用Promise.all
方法)。