资讯专栏INFORMATION COLUMN

js的异步回调之async/await

vspiders / 1015人阅读

摘要:假如返回的不是一个对象,是其他的任何返回值,后面的语句会立即执行。而关键字只有得到返回值后才继续执行,不就是同步么。

最近在学习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里面测试如下图:

所以异步的点在这。而await关键字只有得到返回值后才继续执行,不就是同步么。搞定!!!
async函数返回一个Promise对象,可以使用then()添加回调,catch()捕获异常,当我们也可以用try/catch,就是

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/81730.html

相关文章

  • JS 异步(callback→Promise→async/await)

    摘要:异步编程三座大山原型原型链作用域闭包同步异步。异步操作执行完毕后,再执行该回调函数,确保回调在异步操作之后执行。回调函数本身是我们约定俗成的一种叫法,我们定义它,但是并不会自己去执行它,它最终被其他人执行了。 JS异步编程 JS三座大山:原型原型链、作用域闭包、同步异步。之前有写过自己对闭包的理解,今天来总结一下JS中的异步。 思考(案例来自stackoverflow): functi...

    gougoujiang 评论0 收藏0
  • JavaScript 工作原理四-事件循环及异步编程出现和 5 种更好 async/await

    摘要:函数会在之后的某个时刻触发事件定时器。事件循环中的这样一次遍历被称为一个。执行完毕并出栈。当定时器过期,宿主环境会把回调函数添加至事件循环队列中,然后,在未来的某个取出并执行该事件。 原文请查阅这里,略有改动。 本系列持续更新中,Github 地址请查阅这里。 这是 JavaScript 工作原理的第四章。 现在,我们将会通过回顾单线程环境下编程的弊端及如何克服这些困难以创建令人惊叹...

    maochunguang 评论0 收藏0
  • 笔试题Event Loop终极篇

    摘要:下面开始分析开头的代码第一轮事件循环流程整体作为第一个宏任务进入主线程,遇到,输出遇到函数声明,声明暂时不用管遇到,其回调函数被分发到微任务中。我们记为遇到,其回调函数被分发到宏任务中。 先上一道常见的笔试题 console.log(1); async function async1() { console.log(2); await async2(); con...

    niceforbear 评论0 收藏0
  • ES6-7

    摘要:的翻译文档由的维护很多人说,阮老师已经有一本关于的书了入门,觉得看看这本书就足够了。前端的异步解决方案之和异步编程模式在前端开发过程中,显得越来越重要。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。 JavaScript Promise 迷你书(中文版) 超详细介绍promise的gitbook,看完再不会promise...... 本书的目的是以目前还在制定中的ECMASc...

    mudiyouyou 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<