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