ES7新特性async/await

25 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第20天,点击查看活动详情

前言

昨天学习ES6标准中的Promise新特性,提供了一种更优雅的方式来编写异步编程代码,但在某些情况下还是不够优雅,因此在ES7标准中提供了async/await关键字来进一步优化异步编码方式,下面就来了解一下。

Promise存在的问题

通常我们都需要通过AJAX发送请求给服务器,当存在多个请求并且依赖于上一个ajax的请求结果时,根据Promise的写法我们很容易就会写出如下代码:

function ajaxRequest (url) {
    return new Promise(function (resolve, reject) {
        $.ajax({
            url: url,
            type: 'GET',
            success: function (res) {
                resolve(res);
            },
            error: function(err) {
                reject('请求失败');
            }
        })
    })
};
​
ajaxRequest('justUrl').then((d) => {
    console.log(d);       
    return ajaxRequest(d.url);
}).then((d) => {
    console.log(d);       
    return ajaxRequest(d.url);
}).then((d) => {
    // TODO
    console.log(d); 
}).catch((err)=>{
    console.log( err );
})

在逻辑简单时,如上代码并没有啥问题。但如果请求逻辑复杂,传递参数为对象等,就同样会出现以前的回调地狱。因此在ES7中就提供了async/await这两个关键字。

async/await

async关键字用于声明一个函数是否为异步函数,而await则用于异步函数中的同步等待(只能用于被aysnc关键字声明的函数中)。

async function testAsync() {
    const response = await new Promise(resolve => {
        setTimeout(() => {
            resolve("等待");
        }, 1000);
    });
    console.log(response); // 等待
}
testSync();// testAsync方法本身还是异步

我们通常使用async/await和promise来配合使用,用于实现串行并行等处理实现。

async function testAjaxRequest() {
    let response1 = await ajaxRequest("url1");
    let response2 = await ajaxRequest(response1.url);
    let response3 = await ajaxRequest(response2.url);
}

例如我们通过await就可以很优雅的实现串行请求了,或者实现并行请求

async function asyncAwaitFunction(str) {
    return await new Promise((resolve) => {
        setTimeout(() => {
            resolve(str)
        }, 1000);
    })
}
async function parallel() { 
    const func1 = asyncAwaitFunction('func1') //并行执行
    const func2 = asyncAwaitFunction('func2') //并行执行
}
parallel()

错误处理

当我们使用Promise发送网络请求等操作时,肯定会出现错误情况,当调用reject方法时,我们可以使用try-catch语句进行包裹处理。

async function catchErr() {
    try {
        await new Promise( (resolve, reject) => {
            setTimeout( () => {
                reject( "网络请求出错" ); // 或者throw "error"
             
            }, 1000 );
        })
    }
    catch ( err ) {
        console.log("错误情况",err );
    }
}
catchErr(); //http error...

小细节

  1. await关键字后面应该跟着一个Promise的对象,如果是其他类型的返回值也可以,不过await就没有效果了。
  2. await只能在异步函数中使用

学习资料