zoukankan      html  css  js  c++  java
  • Promise的并行和串行

    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());
    
  • 相关阅读:
    黑马程序员——JAVA基础之主函数main和静态static,静态代码块
    黑马程序员——JAVA基础之final this.和super.的区别
    黑马程序员——JAVA基础之构造函数,构造代码块
    黑马程序员——JAVA基础之简述 类的封装
    黑马程序员——JAVA基础之简述面向对象,类,变量,匿名对象
    NBU Rman异机恢复Oracle
    Oracle的Rman差异增量备份
    rman备份出现ORA-19625
    查询rman备份信息常用指令
    RMAN-06172: no AUTOBACKUP found or specified handle is not a valid copy or piece
  • 原文地址:https://www.cnblogs.com/cloud-/p/8534950.html
Copyright © 2011-2022 走看看