Promise 并行

这个功能Promise自身已经提供,不是本文的重点。主要是依赖Promise.all和Promise.race。

Promise.all是所有的Promise执行完毕后(reject|resolve)返回一个Promise对象。

Promise.race是任意一个Promise对象执行完毕后返回一个Promise对象。

有人可能会说,不是Promise对象reject的时候要catch么,这个嘛,.catch只是.then的一种变体。

详情可以参考Promise.allPromise.race

Promise 串行

这个Promise对象本身没有提供,也是本文的重点。

Promise一单开始执行,执行上是不存在串行执行的,你想想,比如典型的计时的Promise。

const p1 =new Promise((resolve, reject) => {
setTimeout(function () {
resolve(1)
}, 1000)
})
const p2 =new Promise((resolve, reject) => {
setTimeout(function () {
resolve(2)
}, 2000)
})

像上面这种,你怎么去串行,当然是不行的。所以,思路得改变。把上面的Promise修改为如下

const p1 = function () {
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve(1)
}, 1000)
})
},
p2 = function () {
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve(2)
}, 2000)
})
},

哦,不是直接的Promise对象,再利用Promise.then时执行该p1(),使得Promise链条得以继续。

/**
* 顺序执行Promise,并返回结果
* @param {返回promise的函数集合} promises
* @param {每一步的回调函数,非异步,可以考虑后期支持} cb
* @param {附加参数} args
*/
function sequence(promises, cb, ...args) {
const p = Promise.resolve(),
len = promises.length
if (len <= 0) {
return p
}
let i = 0
//如果cb不是函数
if (typeof cb !== 'function') {
cb = null
args = [cb, ...args]
} function callBack(...params) {
return p.then(r => {
return promises[i](r, ...params)
}).then(r => {
++i
cb && cb(r, i, ...params)
return i > len - 1 ? Promise.resolve(r) : callBack(...params)
})
} return callBack(...args)
}

先解释一些一下参数

  • promises: 返回Promise对象的集合
  • cb 执行完每个Promise的回调,传入的参数有
    • r: 上一次Promise执行完毕的返回结果
    • i: 当前Promise的索引值
    • params:其他的传入参数
  • args 其他的传入参数

返回来看,核心就是callback函数,他会顺序执行promises的函数返回Promise,然后取检查是否执行到最后,如果还有Promise等待执行,就调用callback,继续执行下一个,反之,结束。

我们来看一个简单的例子

const p1 = function () {
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve(1)
}, 1000)
})
},
p2 = function () {
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve(2)
}, 2000)
})
},
p3 = function () {
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve(3)
}, 3000)
})
} function printTime() {
console.log(new Date().toLocaleString(), ...arguments)
} const promises = [p1, p2, p3] sequence(promises, function (r, i, ...args) {
console.log('result:' + r, 'index:' + i, 'args:' + args)
}, {
a: 1,
b: 2
},3).then(r => printTime('result:', r)) // 输出结果
result:1 index:1 args:[object Object],3
result:2 index:2 args:[object Object],3
result:3 index:3 args:[object Object],3
2018-3-9 16:43:44 result: 3

可以看到

  1. callback 函数,拿到的参数是,上次的执行结果, 索引值,传入的其他参数
  2. 三个返回Promise的函数是依次执行的
  3. 执行完毕后,我们输出了最后的时间和最后的执行结果

    那么,就达到了Promise的顺序执行

    最后奉上完整代码和下载地址
/**
* 转换为Promise集合
* @param {Promise的集合或者之后后返回promise的函数集合} promises
* @param {附加参数} args
*/
function toPromise(promises, ...args) {
return promises.map(p => typeof p === 'function' ? p(...args) : p)
} /**
* 返回Promise.all
* @param {Promise的集合或者之后后返回promise的函数集合} promises
* @param {附加参数} args
*/
function all(promises, ...args) {
return Promise.all(toPromise(promises, ...args))
} /**
* 返回Promise.race
* @param {Promise的集合或者之后后返回promise的函数集合} promises
* @param {附加参数} args
*/
function race(promises, ...args) {
return Promise.race(toPromise(promises, ...args))
} /**
* 顺序执行Promise,并返回结果
* @param {返回promise的函数集合} promises
* @param {每一步的回调函数,非异步,可以考虑后期支持} cb
* @param {附加参数} args
*/
function sequence(promises, cb, ...args) {
const p = Promise.resolve(),
len = promises.length
if (len <= 0) {
return p
}
let i = 0
//如果cb不是函数
if (typeof cb !== 'function') {
cb = null
args = [cb, ...args]
} function callBack(...params) {
return p.then(r => {
return promises[i](r, ...params)
}).then(r => {
++i
cb && cb(r, i, ...params)
return i > len - 1 ? Promise.resolve(r) : callBack(...params)
})
} return callBack(...args)
} /**
* 顺序执行Promise,并返回结果, 需要主动执行sequence(promises)(6)
* @param {返回promise的函数集合} promises
* @param {附加参数} args
*/
function delaySequence(promises, cb, ...args) {
return function (..._args) {
return sequence(promises, cb, ...[...args, ..._args])
}
} const plus = {
race,
all,
sequence,
delaySequence
} module.exports = plus

这里我应用到了自己编写的 FlowMongoActivity.js,用来顺序执行mongo的操作命令.

这里再贴一份 30-seconds-of-code 里面的runPromisesInSeries

const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());

Promise的并行和串行的更多相关文章

  1. async/await 里的并行和串行

    我们在使用 async/await 语法时,有时会这样用: function getName () { return new Promise((resolve, reject)=>{ setTi ...

  2. 7.JavaScript-Promise的并行和串行

    Promise 并行 Promise.all是所有的Promise执行完毕后(reject|resolve)返回一个Promise对象. 最近在开发一个项目中,需要等接口拿到全部数据后刷新页面,取消l ...

  3. 大叔也说并行和串行`性能提升N倍(N由操作系统位数和cpu核数决定)

    返回目录 并行是.net4.5主打的技术,同时被封装到了System.Threading.Tasks命名空间下,对外提供了静态类Parallel,我们可以直接使用它的静态方法,它可以并行一个委托数组, ...

  4. activiti并行和串行区别

    多实例还有并行.串行区分.以下解释一下什么是并行与串行 并行代表同时进行,如把任务分给5个人来处理,这5个人同时会收到任务,并且可以同时处理,不受各自的影响. 串行代表工作或任务由一个人完成后,再由另 ...

  5. 动画处理<并行和串行>

    并行动画 当多个动画定义同时指向某个组件,并使用动画控制器启动时,就产生了并行动画(Parallel Animation).例如我们可以让一个组件: 移动的同时改变大小 旋转的同时边界颜色闪烁 圆形图 ...

  6. Quarz.net 设置任务并行和任务串行

    如何设置Quarz.net某个任务完成后再继续执行该任务?  Quarz.net 的任务有并行和串行两种: 并行:一个定时任务,当执行时间到了的时候,立刻执行此任务,不管当前这个任务是否在执行中: 串 ...

  7. FS BPM 业余研发(用户详细操作手册--单人串行/并行)之 深圳分公司技术部请假审批流程

    1.FS BPM 简介 BPM软件中BPM是英文字母缩写,大致有二个意思.第一.Business Process Management,即业务流程管理,是一套达成企业各种业 务环节整合的全面管理模式. ...

  8. vue使用技巧:Promise + async + await 解决组件间串行编程问题

    业务场景描述 大家都通过互联网投递过简历,比如在智联.58.猎聘等平台.投递心仪的职位前一般都需要前提创建一份简历,简历编辑界面常规的布局最上面是用户的个人基本信息,如姓名.性别.年龄.名族等,接着是 ...

  9. 任意promise串行执行算法 - 童彪

      // 任意promise串行执行算法 - 童彪 function runAllPromise() { var p1 = new Promise((resove, reject) => { s ...

随机推荐

  1. NULL头文件

    #include<stddef.h> NULL不是C语言基本类型,其定义在stddef.h文件中,作为最基本的语言依赖宏存在.但是随着C/C++的发展,很多文件只要涉及了系统或者标准操作都 ...

  2. vim tab设置为4个空格

    为了vim更好的支持python写代码,修改tab默认4个空格有两种设置方法: 1. vim /etc/vimrc 1 set ts=4 2 set sw=4 2. vim /etc/vimrc 1 ...

  3. Codeforces Round #265 (Div. 2) E

    这题说的是给了数字的字符串 然后有n种的操作没次将一个数字替换成另一个字符串,求出最后形成的字符串的 数字是多大,我们可以逆向的将每个数推出来,计算出他的值和位数记住位数用10的k次方来记 1位就是1 ...

  4. cmd中执行jar文件命令(待参数)

    cmd中执行jar文件命令(待参数) 1,jar文件路径:F:\products 2,cmd命令: --两个日期参数(空格隔开) java -jar F:\products\analysis.jar ...

  5. 20145315 《Java程序设计》第七周学习总结

    20145315 <Java程序设计>第七周学习总结 教材学习内容总结 第十三章 时间与日期 13.1.1时间的度量 1.格林威治时间(GMT):参考太阳到达最高点,有时间误差. 2.世界 ...

  6. HDU 3065 病毒侵袭持续中(AC自动机)题解

    题意:要你找到主串中每个模式串的个数. 思路:题目都没说是多组数据,结果没while(~)直接WA了,和上一题差不多,可以用map或者开个数组储存.指针要记得回收内存,不然MLE. #include& ...

  7. luogu p3366 最小生成树模板

    倒腾了一个小时  自己也没去看网上的 总算自己能写出来模板了 kruskal //最小生成树 每次找最短的边 #include<bits/stdc++.h> using namespace ...

  8. python文件操作的坑( FileNotFoundError: [Errno 2] No such file or directory...)

    环境:Windows8.1, Python3.6  pycharm community 2017   c盘下有一个配置文件:setup   with open('c:\\setup','r') as ...

  9. BZOJ 1951 【SDOI2010】 古代猪文

    题目链接:古代猪文 好久没写博客了,这次就先写一篇吧…… 题面好鬼……概括起来就是:给出\(N,G(\leqslant 10^9)\),求:\[G^{\sum_{d|n}\binom{n}{d}} \ ...

  10. Spring IOC和IOC容器

    IOC的核心理念即是控制反转.将对依赖的控制从具体业务对象手中转交到平台或框架中,需要的时候再由平台或框架注入到具体业务对象中.可以说依赖注入是控制反转的实现方式. IOC的优点: 降低代码耦合度 减 ...