如何优雅地写JS串行异步逻辑

2018-11-16 admin

随着现代浏览器的不断发展,相信大家渐渐对ES6中的Promise已经有很多的使用了,其中对Promise.all估计也用的很多。Promise.all就是并行执行多个任务,然后在所有任务成功后触发then里面的内容,或者任意一个任务失败后触发catch里面的内容。

虽然Promise.all非常好用,但它也不是适合所有的场景,最常见的就是有些场景是需要串行的,一个任务列表要按顺序依次循环执行,任意一个失败就不触发下面的任务。那要实现这样的功能能怎么写呢?

最简单的就是一个个写


var a = ()=>{return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000);
});}

var b = ()=>{return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000);
});}

var c = ()=>{return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000);
});}

a().then(()=>{
    return b()
}).then(()=>{
    return c()
}).then(()=>{
    console.log('after 3 sec')
})

这样写。。。真的好挫,更重要的是,有时候需要批量处理一个任务,都是调用同一个函数处理不定长度的数据,这样写肯定就不行了,比如要串行请求一串url。首先想到的是一个比较绕的方法,搞个Promise链出来,把下一个任务作为参数传到前一个的then中,如此循环。这种同一个函数不断循环然后把前一个处理完的值又传到参数里面,刚好和Array.reduce的思想是一致的,所以可以这么写:

var urlArr = ['http://www.qq.com','http://www.qq.com','http://www.qq.com'];

function makaPromiseList(dataArr,handler) {
    return dataArr.reduce((promise, obj) => {
        return promise.then((ret) => {
            return handler(obj);
        })
    }, Promise.resolve())
}

var result = [];
function makeRequest(url){
    return new Promise((resolve,reject)=>{
        $.get(url).success((ret)=>{
            result.push(ret)
            resolve(result)
        }).fail(()=>{
            reject()
        })
    })
}

makaPromiseList(urlArr,makeRequest).then((result)=>{
    console.log(result)
});

老师不给力啊,理解起来就很绕,还要在闭包外面定义result存数据,用上reduce也觉得有点奇技淫巧,不太美观啊,能不能写得更好看点啊。 可以!说起异步方案,Promise是很强,但它还不是最强的,还有Promise的进阶版 —— async/await!号称JS异步的终极解决方案,真不是盖的,下面就来看看async/await的方案

var urlArr = ['http://www.qq.com','http://www.qq.com','http://www.qq.com'];

function makeRequest(url){
    return new Promise((resolve,reject)=>{
        $.get(url).success((ret)=>{
            resolve(ret)
        }).fail(()=>{
            reject()
        })
    })
}

async function makaPromiseList(dataArr,handler){
    var result = [];
    for(let item of dataArr){
        var ret = await handler(item);
        result.push(ret);
    }
    return result;
}
makaPromiseList(urlArr,makeRequest).then((ret)=>{
    console.log(ret)
});

一个for循环解决串行异步问题,没有回调没有嵌套看起来瞬间舒服多了~

原文链接:http://blog.leanote.com/post/ycp424c/串行promise任务

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-45565.html

文章标题:如何优雅地写JS串行异步逻辑

相关文章
Vue.js组件tab实现选项卡切换
本文实例为大家分享了vue插件tab选项卡的具体代码,供大家参考,具体内容如下 效果图: 代码如下: <!DOCTYPE html> <html lang="en"> <head> ...
2017-03-13
JavaScript教程:JS中的原型
Keith Peters 几年前发表的一篇博文,关于学习没有“new”的世界,其中解释了使用原型继承代替构造函数。两者都是纯粹的原型编码。 标准方法(The Standard Way) 一直以来,我们学习的在 JavaScript 里创建对...
2015-11-12
three.js实现围绕某物体旋转
话不多说,请看代码: 可以拖动右上角观察变化 <!DOCTYPE html> <html lang="en" style="width: 100%; height:100%;"&gt...
2017-02-17
NodeJS参考手册pdf版
下载地址:Nodejs参考手册PDF版下载 ...
2015-11-12
Node.js学习(1)----HTTP服务器与客户端
Node.js 标准库提供了 http 模块,其中封装了一个高效的 HTTP 服务器和一个简易的HTTP 客户端。http.Server 是一个基于事件的 HTTP 服务器,它的核心由 Node.js 下层 C++部分实现,而接口由 Jav...
2015-11-12
Riot.js:不足1KB的MVP客户端框架
Riot.js是一款MVP(模型-视图-呈现)开源客户端框架,其最大的特点就是体积非常小,不足1KB,虽然体积小,但它可以帮助用户构建大规模的Web应用程序。 Riot.js是由Moot公司开发,目前最新版本为v0.9.2,遵循MIT开源许...
2016-03-11
使用jspdf生成pdf报表
由于前台html已经动态生成报表,而且,前台有一个功能,一个date range组件,当你拖动的时候,报表会在不提交到后台的情况下动态变化。 因此需要用到js生成生报表: 用到的组件: jquery.js jspdf.js canvg.js...
2017-03-25
AngularJS vs. jQuery,看看谁更胜一筹
很多Web开发新手都会有这样的疑问“我应该使用什么开发框架呢,如何快速学会Web开发呢?”这个问题其实没有一个统一的正确答案,其中讨论最多的就是AngularJS和jQuery的差别。这两者的之间的比较很微妙,有时就像拿苹果和橘子在作比较,...
2015-11-12
如何为高负载网络优化Nginx 和 Node.js?
译者:AlfredCheung 在搭建高吞吐量web应用这个议题上,NginX和Node.js可谓是天生一对。他们都是基于事件驱动模型而设计,可以轻易突破Apache等传统web服务器的C10K瓶颈。预设的配置已经可以获得很高的并发,不过,...
2015-11-12
javaScript+turn.js实现图书翻页效果实例代码
为了实现图书翻页的效果我们在网上可以看到很多教程 在这里推荐turn.js 网上的turn.js 有api 不过是英文的  很多人看起来不方便 .关于代码也是奇形怪状在这里我将详细讲解如何使用turn.js实现翻页效果 ,本篇文章只是讲解 ...
2017-03-16
回到顶部