Promise 并行
这个功能Promise自身已经提供,不是本文的重点。主要是依赖Promise.all和Promise.race。
Promise.all是所有的Promise执行完毕后(reject|resolve)返回一个Promise对象。
Promise.race是任意一个Promise对象执行完毕后返回一个Promise对象。
有人可能会说,不是Promise对象reject的时候要catch么,这个嘛,.catch只是.then的一种变体。
详情可以参考Promise.all和Promise.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],3result:2 index:2 args:[object Object],3result:3 index:3 args:[object Object],32018-3-9 16:43:44 result: 3可以看到
- callback 函数,拿到的参数是,上次的执行结果, 索引值,传入的其他参数
- 三个返回Promise的函数是依次执行的
- 执行完毕后,我们输出了最后的时间和最后的执行结果
那么,就达到了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这里我应用到了自己编写的 Flow的MongoActivity.js,用来顺序执行mongo的操作命令.
这里再贴一份 30-seconds-of-code 里面的runPromisesInSeries
const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());版权声明
本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。



