• 等待者模式


    等待者模式

    等待者模式是通过对多个异步任务进行监听,当异步任务完成后触发未来发生的动作,在没有Promise这个模型的时候,其实就已经出现这样类似的技术方案,不同的只是没有定制为一个技术规范,等待者模式不属于一般定义的23种设计模式的范畴,而通常将其看作广义上的技巧型设计模式。

    描述

    等待者模式就是通过对异步进程监听,来触发未来发生的动作,举个例子当异步进程操作A、B需要都完成以后才能进行C进程操作,在开发中经常会这样,需要等到上个操作完成或者知道上个操作完成才去触发下个操作,而JavaScript又是单线程的,不能采用阻塞的方式去处理,在Promise规范出现之前通常都是使用回调的方式实现,这样很容易造成回调地狱,等待者模式就是在Promise规范制定之前一个类似于Promise的解决方案,可以算是Promise规范的一个参考前身。

    实现

    var Waiter = function() {
        var dfd = []; // 等待对象容器
        var doneArr = []; // 成功回调容器
        var failArr = []; // 失败回调容器
    
        //监控对象类
        var Promise = function() {
            this.resolved = false; // 监控对象是否解决成功状态
            this.rejected = false; // 监控对象是否解决失败状态
        }
    
        Promise.prototype = {
            //解决成功
            resolve: function() {
                this.resolved = true; // 设置当前监控状态是成功
                if (!dfd.length) return void 0;
                for (var i = dfd.length - 1; i >= 0; i--) {
                    // 对象监控对象遍历如果任一个对象没有解决或者失败就返回
                    if (dfd[i] && !dfd[i].resolved || dfd[i].rejected) return void 0;
                    dfd.splice(i, 1);
                }
                _exec(doneArr);
            },
            //解决失败
            reject: function() {
                this.rejected = true; // 设置当前监控状态是失败
                if (!dfd.length) return void 0; // 没有监控对象取消
                dfd.splice(0); // 清除监控对象
                _exec(failArr);
            }
        }
    
        this.Deferred = function() {
            return new Promise();
        };
    
        //回调执行方法
        function _exec(arr) {
            for (let i = 0, len = arr.length; i < len; i++) {
                try {
                    arr[i] && arr[i]();
                } catch (e) {
                    // console.warn("Error", e);
                    _exec(failArr);
                }
            }
        };
    
        // 监控异步方法参数
        this.when = function(...args) {
            //设置监控对象
            dfd = args;
            var i = args.length;
            //向前遍历监控对象
            for (--i; i >= 0; i--) {
                //不存在监控对象 监控对象已经解决 监控对象失败
                if (!args[i] || args[i].resolved || args[i].rejected || !args[i] instanceof Promise) {
                    args.splice(i, 1)
                }
            }
            return this; // 返回等待者对象
        };
    
        //解决成功回调函数添加方法
        this.done = function(...args) {
            doneArr = doneArr.concat(args); // 向成功毁掉函数容器中添加回调方法
            return this;
        };
    
        //解决失败回调函数添加方法
        this.fail = function(...args) {
            failArr = failArr.concat(args); // 向失败回调函数中添加方法
            return this;
        };
    }
    
    ;(function(){
        var waiter = new Waiter(); // 创建一个等待者实例
        var first = function() {
            var promise = waiter.Deferred();
            setTimeout(() => {
                promise.resolve();
            }, 1000);
            return promise; // 返回监听这对象
        }();
        var second = function() { // 第二个对象
            var promise = waiter.Deferred();
            setTimeout(() =>  {
                promise.resolve();
            }, 2000);
            return promise;
        }();
        waiter.when(first, second).done(() => {
            console.log("success");
        }).fail(() => {
            console.log("fail");
        })
    })();
    
    ;(function(){
        var waiter = new Waiter(); // 创建一个等待者实例
        var first = function() {
            var promise = waiter.Deferred();
            setTimeout(() => {
                promise.resolve();
            }, 1000);
            return promise; // 返回监听这对象
        }();
        var second = function() { // 第二个对象
            var promise = waiter.Deferred();
            setTimeout(() => {
                promise.resolve();
            }, 3000);
            return promise;
        }();
        waiter.when(first, second).done(() => {
            throw new Error("test");
        }).fail(() => {
            console.log("fail");
        })
    })();
    

    Promise

    Promise就是异步操作的一个解决方案,用于表示一个异步操作的最终完成或失败及其结果值,Promise有各种开源实现,在ES6中被统一规范,由浏览器直接支持。上面我们实现的等待者模式更类似于Promise.all()

    示例

    这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常被用于处理多个promise对象的状态集合。

    var p1 = new Promise((resolve, reject) => {
      resolve("success1");
    })
    
    var p2 = new Promise((resolve, reject) => {
      resolve("success2");
    })
    
    var p3 = new Promise((resolve, reject) => {
      reject("fail");
    })
    
    Promise.all([p1, p2]).then((result) => {
      console.log(result);     // 成功状态 // ["success1", "success2"]
    }).catch((error) => {
      console.log(error);
    })
    
    Promise.all([p1,p3,p2]).then((result) => {
      console.log(result);
    }).catch((error) => {
      console.log(error);      // 失败状态 // fail
    })
    

    每日一题

    https://github.com/WindrunnerMax/EveryDay
    

    参考

    https://juejin.cn/post/6844903645855612942
    https://segmentfault.com/a/1190000021413444
    https://www.cnblogs.com/hsp-blog/p/5889842.html
    
  • 相关阅读:
    KFC
    肯德基champs各个字母代表什么_百度知道
    《一席》更新至93—教育—优酷网,视频高清在线观看
    童启华:一个做包子的—在线播放—《一席》—教育—优酷网,视频高清在线观看
    甘其食_百度百科
    乡村基关闭北京上海全部门店 退回西南市场_网易财经
    出兑_百度百科
    美食广场
    架构师招聘-民生电子商务有限责任公司-北京招聘-智联招聘
    架构师招聘-民生电子商务有限责任公司-北京招聘-智联招聘
  • 原文地址:https://www.cnblogs.com/WindrunnerMax/p/14200654.html
Copyright © 2020-2023  润新知