一、含义
学过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
方法)。