设计模式知识连载(44)---等待者模式:

<body>


<h3>设计模式知识连载(44)---等待者模式:</h3>
<p>
    通过对多个异步进程监听,来触发未来发生的动作
</p>

<hr>


<script type="text/javascript">



    /**
    *   案例一:接口拆分,方式一:初始
    */
    // 等待者对象
    var Waiter = function() {
        // 注册了等待对象容器
        var dfd = [] ;
        // 成功回调方法容器
        var doneArr = [] ;
        // 失败回调方法容器
        var failArr = [] ;
        // 缓存Array方法slice
        var _slice = Array.prototype.slice ;
        // 保存当前等待者对象
        var that = this ;

        // 监控对象类
        var Primise = function() {
            // 监控对象是否解决成功状态
            this.resolved = false ;
            // 监控对象是否解决失败状态
            this.rejected = false ;
        }
        // 监控对象类原型方法
        Primise.prototype = {
            // 解决成功
            resolve : function() {
                // 设置当前监控对象解决成功
                this.resolved = true ;
                // 如果没有监控对象则取消执行
                if(!dfd.length) {
                    return ;
                }
                // 遍历所有注册了的监控对象
                for(var i = dfd.length - 1; i >= 0; i--) {
                    // 如果有任意一个监控对象没有被解决或者解决失败则返回
                    if(dfd[i] && !dfd[i].resolved || dfd[i].rejected) {
                        return ;
                    }
                    // 清除监控对象
                    dfd.splice(i, 1) ;
                }
                // 执行解决成功回调方法
                _exec(doneArr) ;
            },
            // 解决失败
            reject : function() {
                // 设置当前监控对象解决失败
                this.rejected = true ;
                // 如果没有监控对象则取消执行
                if(!dfd.length) {
                    return ;
                }
                // 清除所有监控对象
                dfd.splice(0) ;
                // 执行解决成功回调方法
                _exec(failArr) ;
            }
        }

        // 创建监控对象
        that.Deferred = function() {
            return new Primise() ;
        }

        // 回调执行方法
        function _exec(arr){
            var i = 0 ;
            var len = arr.length ;
            // 遍历回调数组执行回调
            for(; i < len; i++) {
                try {
                    // 执行回调函数
                    arr[i] && arr[i]() ;
                }catch(e) {

                }
            }
        }

        // 监控异步方法 参数:监控对象
        that.when = function() {
            // 设置监控对象
            dfd = _slice.call(arguments) ;
            // 获取监控对象数组长度
            var i = dfd.length ;
            // 向前遍历监控对象,最后一个监控对象的索引值为length-1
            for(--i; i >= 0; i--) {
                // 如果不存在监控对象,或者监控对象已经解决,或者不是监控对象
                if(!dfd[i] || dfd[i].resolved || dfd[i].rejected || !dfd[i] instanceof Primise) {
                    // 清理内存,清除当前监控对象
                    dfd.splice(i, 1) ;
                }
            }
            // 返回等待者对象
            return that ;
        }

        // 解决成功回调函数添加方法
        that.done = function() {
            // 向成功回调函数容器中添加回调方法
            doneArr = doneArr.concat(_slice.call(arguments)) ;
            // 返回等待者对象
            return that ;
        }

        // 解决失败回调函数添加方法
        that.fail = function() {
            // 向失败回调函数容器中添加回调方法
            failArr = failArr.concat(_slice.call(arguments)) ;
            // 返回等待者对象
            return that ;
        }
    }

    // 测试用例:


    // 创建一个等待者对象
    var waiter = new Waiter() ;

    // 第一个彩蛋,3秒停止
    var first = (function() {
        // 创建监听对象
        var dtd = waiter.Deferred() ;
        setTimeout(function() {
            console.log('first finish') ;
            // 发布解决成功问题
            dtd.resolve() ;
            // 发布解决失败问题
            // dtd.reject() ;
        }, 3000) ;
        // 返回监听对象
        return dtd ;
    })() ;

    // 第二个彩蛋,6秒后停止
    var second = (function() {
        // 创建简体你对象
        var dtd = waiter.Deferred() ;
        setTimeout(function() {
            console.log('second finish') ;
            // 发布解决成功消息
            dtd.resolve() ;
            // 发布解决失败问题
            // dtd.reject() ;
        }, 6000) ;
        // 返回监控对象
        return dtd ;
    })() ;

    // 监听两个彩蛋的工作状态,并执行相应的成功回调函数与失败回调函数
    waiter
        // 监听两个彩蛋
        .when(first, second)
        // 添加成功回调函数
        .done(function() {
            console.log('success') ;
        }, function() {
            console.log('success again') ;
        })
        // 添加失败回调函数
        .fail(function() {
            console.log('fail') ;
        }) ;



    /**
    *   案例二:封装异步请求,方式一:初始
    */  
    // 封装get请求
    var ajaxGet = function(url, success, fail) {
        var xhr = new XMLHttpRequest() ;
        // 创建监测对象
        var dtd = waiter.Deferred() ;
        xhr.onload = function(event) {
            // 请求成功
            if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
                success && success() ;
            // 请求失败 
            }else {
                dtd.reject() ;
                fail && fail() ;
            }
        } ;
        xhr.open('get', url, true) ;
        xhr.send(null) ;
    }



    /**
    *   案例三:轮询,方式一:初始
    */  
    // 长轮询
    (function getAjaxData() {
        // 保存当前函数
        var fn = arguments.callee ;
        setTimeout(function() {
            $.get('./test.php', function() {
                console.log('轮询一次') ;
                // 再一次执行轮询
                fn() ;
            }) ;
        }, 5000) ;
    })() ;
</script>    

</body>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值