简单聊一聊「前端异步编程」的实现方式

Posted 木星记note

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单聊一聊「前端异步编程」的实现方式相关的知识,希望对你有一定的参考价值。

当前浏览器不支持播放音乐或语音,请在微信或其他浏览器中播放 简单聊一聊「前端异步编程」的实现方式

——本文借鉴于阮一峰老师的「es6标准入门(第3版)」

简单聊一聊「前端异步编程」的实现方式

前言:

        一直以忙为借口,偷懒了一年

        最近刚巧团队内在推广技术氛围,硬性要求每两周更新一篇技术博文

        于是乎,以此为契机,我会重拾更文哈

        之后的文章更多地会跟技术有关,看不懂又有兴趣的同学欢迎了解一下「前端开发」

        好了,废话不多说,让我们开始正文吧



在之前,常用异步编程的方式大概有下面4种
1、回调函数
2、事件监听
3、发布/订阅
4、Promise  对象

首先介绍下第一位嘉宾——
回调函数
所谓回调函数,
就是把任务的第二段单独写在一个函数里,等到重新执行这个任务时便直接调用这个函数。

下面举一个最常见的发起请求的例子


a.request({

    url: '/test',

    data: {}

}, function(){

    console.log('我就是回调函数');

});


现在看来这个回调函数没什么问题,那如果有一个业务场景是要按顺序请求多次呢?

看下面这个例子


a.request({

    url: '/test1',

    data: data1

}, function(){

    a.request({

        url: '/test2',

        data: data2

    }, function(){

        a.request({

            url: '/test3',

            data: data3

        }, function(){

            // ...

        });

    });

});


这里request方法封装了一个jquery的$.ajax发起请求方法,回调函数在其成功回调里执行

不难想象,如果有多次请求,就会出现多重嵌套。

此时代码不是纵向发展,而是横向发展,很快就会乱成一团,无法管理。这种情况就被称为“回调函数地狱“(callback hell)。


此时,介绍下第二位嘉宾——Promise

Promise对象就是为了解决callback hell而被提出的。

它是一种新的写法,允许将回调函数的嵌套改写成链式调用。

继续上面的例子,如果改成Promise的写法,就会变成下面这个样子


a.request({

    url: '/test1',

    data: data1

}).then(function(){

    url: '/test2',

    data: data2

}).then(function(){

    url: '/test3',

    data: data3

});


这里request封装了一个用Promise发起请求的方法,返回的是一个Promise对象。

Promise提供then方法加载回调函数,catch方法捕捉执行过程中抛出的错误。

可以看到,Promise的写法只是回调函数的改进,使用then方法以后,异步任务的两段执行更清楚了,除此以外,并无新意。

Promise的最大问题是代码冗余,原来的任务被Promise包装以后,无论什么操作,一眼看上去都是许多then的堆积,原来的语义变得很不清楚。

那么,有没有更好的写法呢?


当当当当,此时第三位嘉宾隆重登场——async

先来看看,使用async再次执行上面的例子


(async function(){

    await a.request({

        url: '/test1',

        data: data1

    });

    await a.request({

        url: '/test2',

        data: data2

    });

    await a.request({

        url: '/test3',

        data: data3

    });

})()


可以看到,async对比之前的写法有以下几个优点

1、更好的语义

async 表示函数里有异步操作

await 表示紧跟在后面的表达式需要等待结果


2、更清晰的流程

将异步写法变成了同步写法,流程管理看上去更清晰


下面简单说一下async的用法

async函数返回一个Promise对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

下面看一个在实际业务中简单使用的例子


//这是一个查询列表及其详情并渲染的过程

let data = {

    // 查询参数若干...

};

(async function(){

    //第一步,获取同步码

    let asyncCode = await getAsyncCode();

    

    //第二步,将asyncCode塞入查询参数里,然后开始真正查询

    data.asyncCode = asyncCode;

    await queryTrade(data);

    

    //第三步,获取同步状态,并渲染页面表格

    let list = await getSyncStatus(asyncCode);

    updatePackageList(list);

    

    //第四步,获取包裹详情,并渲染

    let detail = await getTradeDetail(list);

    updatePackageDetail(detail);

})();


await 后面封装的函数是发起对应请求的方法,updateXXX方法是渲染页面的方法

可以看到,流程管理清晰了许多。


好啦,本次先聊到这里,走过路过,喜欢的朋友点个赞啦,有什么想说的或者补充的,也欢迎踊跃留言。


咱们下期再见。


以上是关于简单聊一聊「前端异步编程」的实现方式的主要内容,如果未能解决你的问题,请参考以下文章

异步编程到底在说啥?

异步编程到底在说啥?

聊一聊Unity协程背后的实现原理

聊一聊Unity协程背后的实现原理

聊一聊Unity协程背后的实现原理

聊一聊Unity协程背后的实现原理