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); });}