async/await是Javascript的异步流程控制的一种方案,可以在async函数里面用同步的写法来实现异步的操作,使用非常方便
async函数
async函数不同于generator函数和普通函数,总是返回一个promise对象(后文用p表示),如果async函数有返回值,使用p.then
来获取,如果async函数有抛出错误,使用p.catch
来获取
await表达式
await会“暂停”当前async函数的执行,返回promise处理的结果,然后继续往下执行
await只能在async函数里面执行
举个栗子
async function getBook(url) {
let book = await rp(url, {json: true});
if (!book) {
throw new Error('No book...')
}
return book;
}
let gb = getBook('https://api.douban.com/v2/book/isbn/9787115299710');
gb.then(res => {
// return value;
console.log(res);
}).catch(err => {
// throw error
console.log(err);
});
避免错误使用
在编写代码的时候,使用的是同步的写法,但是其实内部运行还是异步的。举个栗子
function getBook (url) {
console.log(`sending book url is ${ url }`);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('book data');
}, 3000)
})
}
function getMusic (url) {
console.log(`sending music url is ${ url }`);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('music data');
}, 1000);
});
}
上面模拟两个异步请求getBook和getMusic,分别是3秒和1秒后返回数据
function getBook (url) {
console.log(`sending book url is ${ url }`);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('book data');
}, 3000)
})
}
function getMusic (url) {
console.log(`sending music url is ${ url }`);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('music data');
}, 1000);
});
}
从结果可以看出,从请求到输出耗时4s左右,虽然看起来没什么问题,但是还是可以优化的,因为两个接口无相互依赖,所以可以实现并行请求的,减低请求消耗的时间,改为下面这种写法
async function getData() {
let gBook = getBook('https://www.baidu.com');
let gMusic = getMusic('https://tmall.com');
let music = await(gMusic);
let book = await(gBook);
}
对比两种写法,第一种获取到book和music所需要的时间是4s左右,第二种只需要3s左右,减少了1s左右的延迟
Promise.all
另外如果要并行请求多个相同url的请求,可以使用Promise.all
方法来获取结果,例如
async function getBookByIds (ids) {
let books = ids.map(async id => {
// await加不加都一样?
return await getBookById(id);
});
Promise.all(books).then(res => {
console.log(res);
});
}