1

最近在学习NodeJS框架koa V2,koa2的API很简单,基于ES7 async/await实现异步代码。很多人认为async/await是解决异步终极解决方案,那我们就研究下async/await。
前端业务逻辑越来越复杂,往往几个 AJAX 请求之间互有依赖,有些请求依赖前面请求的数据,有些请求需要并行进行。我们用ajax来做个例子,根据查找一个省份中的第一个市的区县。

$.get('/url/city',[province:'河北省'],function (result1){
    console.log(result1);
    $.get('/url/county',[city:result1[1]],function (result2){
        console.log(result2);
    })
})

这个是用回调函数执行的异步操作,大量的异步操作就有大量的回调函数,现在我们是嵌套来三层,假如我们嵌套了四层五层更多层,这个时候使用回调函数来写代码往往会导致代码难以阅读,就会形成了回调地狱Callback hell。
现在我们用比较优雅一点的,看起来像同步实则异步的async/await 重构一下代码。

    var requestUrl=(url,args)=>{
     return new Promise(function(resolve,reject){
        $.get(url,args,(result)=> {
             try {
                  resolve(JSON.parse(result));
             }catch(e){
                  reject(e);
             }    
         }) 
     })
    
}
async function getCounty(province){
    try{
        let result1=await requestUrl('/url/city',{provinces:province});
        console.log(result1);
    }catch(e){
        console.log(e);
    }
    try{
        let result2=await requestUrl('/url/county',{city:result1[1]});
        console.log(result2);
    }catch(e){
        console.log(e);
    }
};
getCounty('河北省');

首先我们定义了一个requestUrl函数,这个函数返回一个Promise对象resolve,并拿到结果,立即执行函数定义时使用了关键字async,在函数体中配合使用了await,执行第一个await会返回‘/url/province’的执行数据所有河北省的市,执行第二个await,返回根据第一个市里面的区县。

现在我们了解一下async/await的用法;

async关键字表示这个是一个异步函数,await只能使用在这个函数里面,如果是在普通函数就会报错;
await的作用是获取一个promise对象,获取返回值之前await后面的语句是无法继续执行的。假如await返回的不是一个promise对象,是其他的任何返回值,await后面的语句会立即执行。

ajax比较容易看出call hell问题,现在我们弄个简单的例子,可以在babel中执行一下。

var sleep = function (time) {
        setTimeout(function () {
            console.log('test');
        }, time);
};
var start = async function () {
    console.log('start');
    await sleep(3000);
    console.log('end');
};

start();
这个是没有返回promise对象的例子,执行start()后,先输出’start‘,然后'end',三秒钟后输出'test';

var sleep = function (time) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve('test');
            console.log('test');
        }, time);
    })
};
async function start() {
    console.log('start');
    let result = await sleep(8000);
    console.log('end');
};
start();

这个是返回promise对象,它先输出‘start’,然后是等待三秒输出‘test’,最后输出‘end’;

在学习过程中,我被一句话给误导了,‘看起来像同步实则异步的async/await’,就走到了一个死胡同里,await关键字声明一个异步函数,但是await阻止了await后面语句执行,只有await等到了一个返回值才会继续执行,这不就是同步执行了吗?彻底的懵了,后来恍然大悟,async声明start()为异步函数,假如再有一个start2(),它们并行执行的,在babel里面测试如下图:
clipboard.png
所以异步的点在这。而await关键字只有得到返回值后才继续执行,不就是同步么。搞定!!!
async函数返回一个Promise对象,可以使用then()添加回调,catch()捕获异常,当我们也可以用try/catch,就是


泽浩沉
288 声望18 粉丝

希望自己能够自由地对各种事情发表自己的意见