zoukankan      html  css  js  c++  java
  • JavaScript设计模式--桥梁模式--XHR连接队列

    针对该模式的例子现在不是很理解,写下来慢慢熟悉。

    们要构建一个队列,队列里存放了很多ajax请求,使用队列(queue)主要是因为要确保先加入的请求先被处理。任何时候,我们可以暂停请求、删除请求、重试请求以及支持对各个请求的订阅事件。

    (1)异步请求的函数封装

    /*
    * XHR连接对象
    * 把请求的函数做成一个序列,按照执行序列来完成每一个序列项的任务
    *
    * */
    (function () {
        //(1)一个request请求
        var asyncRequest=(function () {
            //
           function handleReadyState(o,callBack) {
                //设置浏览器每隔半秒执行一次函数
               var poll=window.setInterval(function () {
                   //4表示:交互完成
                   if(o && o.readyState==4){
                     //这种写法类似长连接的写法,如果不成功总是请求你(半秒请求一次)
                     window.clearInterval(poll);
                 if(callBack){
                     callBack(o);
                 }
                   }
               },500)
           }
    
           //(2)获取XHR的工厂
            var getXHR=function () {
                var http;
                 try{
                     http=new XMLHttpRequest();
                     getXHR=function () {
                      return new XMLHttpRequest();
                    }
                 }catch(e){
                var msxml=[
                    'MSXML2.XMLHTTP.3.0',
                    'MSXML2.XMLHTTP',
                    'MICROSOFT.XMLHTTP'
                ];
                for(var i=0;i<msxml.length;i++){
                    try {
                        http=new ActiveXObject(msxml[i]);
                        getXHR=function () {
                            return new ActiveXObject(msxml[i]);
                        };
                        break;
                    }catch(e){}
                }
              }
              return http;
            }
            //(3)核心函数   使用返回一个单体
            return function (method,url,callback,postData) {
                    var http=getXHR();
                    http.open(method,url,true);//打开
                    handleReadyState(http,callback);//回掉连接直到成功
                http.send(postData||null);
            }
        })();
        //(4)为了能添加链式调用的模板
    Function.prototype.method=function (name,fn) {
           this.prototype[name]=fn;
           return this;
    }
    
    //扩展array方法
        //循环
        if(!Array.prototype.forEach){
            Array.method("forEach",function (fn,thisObj) {
                var scope=thisObj||window;
                for(var i=0;i<this.length;i++){//Array
                fn.call(scope,this[i],i,this);
                }
            })
        }
        //过滤
        if(!Array.prototype.filter){
            Array.method("filter",function (fn,thisObj){
             var scope=thisObj||window;
              var a=[];
         for(var i=0;i<this.length;i++){
              if(!fn.call(scope,this[i],i,this)){//???
                    continue;
              }
              a.push(this[i]);
            }
            })
            return a;
        }
    })()

    (2)建立一个简单的观察者模式

    /*
    *一个简答简单的观察者模式
    * */
    (function () {
        //1,利用空对象来设立命名空间
        window.DED=  window.DED||{};
        DED.util= DED.util||{};
        //观察者
        DED.util.Observer=function () {
            this.fns=[];
        }
        //扩展方法
        DED.util.Observer.prototype= {
            //观察 添加
            subscribe: function (fn) {
                this.fns.push(fn);
            },
            //取消  观察
            unsubscribe: function (fn) {
                this.fns = this.fns.filter(function (el) {
                    if (el != fn) {
                        return el;
                    }
                })
            },
            //循环执行被观察的数组
            fire: function (o) {
                this.fns.forEach(function (el) {
                    el(o);
                })
            }
        }
            //序列
            /*
            * 使用了观察者,序列可以装载任何对象,对象内容函数的调用方法不是由队列来完成,是观察者来执行的。
            * */
            DED.Queue=function () {
             //定义一个空队列
                this.queue=[];
             //成功观察
                this.onComplete=function () {new   DED.util.Observer();}
             //失败的观察
                this.onFailure=function () {new   DED.util.Observer();}
             //刷新观察
             this.onFlush=function () {new   DED.util.Observer();}
             //重复次数
            this.retryCount=3;
             //当前执行次数
             this.currentRetry=0;
             //停顿
             this.paused=false;
             //请求超时时间
              this.timeout=5000;
             //连接对象
               this.conn={};
             //计时器
             this.timer={};
        }
    
        //静态函数添加
        DED.Queue.method("flush",function () {//刷新
          if(!this.queue.length>0){
              return ;
          }
          //如果是停顿状态,也不刷新
            if(this.paused){
              this.paused=false;
              return ;
            }
            var self=this;
            //当前连接次数+1
            this.currentRetry++;
            var abort=function () {
                //可以停止一个XMLHttpRequest对象的Http请求
                self.conn.abort();
                if(self.currentRetry==self.retryCount){
                   //执行失败过的序列
                self.onFailure.fire();
                //重置当前次数
                    self.currentRetry=0;
                }else {
                    self.flush();
    
                }
                //计时器
                this.timer=window.setTimeout(abort,this.timeout);
                //准备回调
                var callback=function (o) {
                    //清除定时器
                    window.clearTimeout(self.timer);
                    //把当前次数清零
                    self.currentRetry=0;
                    //本着先进先出的原则,把队列反序排序
                    self.queue.shift();
                    //执行队列
                    self.onFlush.fire(o.responseText);
                    if(self.queue.length==0){
                        //如果队列等于0执行默认的成功队列
                        self.onComplete().fire();
                        return ;
                    }
                    self.flush();//递归
                }
                //改变连接对象
                this.conn=asyncRequest(
                    this.queue[0]['method'],
                    callback,
                    this.queue[0]['parmas']
                )
            }
        }).method("setRetryCount",function (count) {
            this.retryCount=count;
        }).method("setTimeOut",function (time) {
            this.timer=time;
        }).method("add",function (o) {
            this.queue.push(o);
        }).method("pause",function () {
            this.paused=true;
        }).method("clear",function () {
            this.queue=[];
        }).method("dequeue",function () {//
            this.queue.pop();
        })
    })()

    总结

    桥接模式的优点也很明显,我们只列举主要几个优点:

    1. 分离接口和实现部分,一个实现未必不变地绑定在一个接口上,抽象类(函数)的实现可以在运行时刻进行配置,一个对象甚至可以在运行时刻改变它的实现,同将抽象和实现也进行了充分的解耦,也有利于分层,从而产生更好的结构化系统。
    2. 提高可扩充性
    3. 实现细节对客户透明,可以对客户隐藏实现细节。

    同时桥接模式也有自己的缺点:

    大量的类将导致开发成本的增加,同时在性能方面可能也会有所减少。

  • 相关阅读:
    Shell脚本定期清空大于1G的日志文件
    Shell脚本实现监视指定进程的运行状态
    Shell脚本实现根据文件的修改时间来分类文件
    通过Shell统计PV和UV
    Python之Html解析方法
    Http请求的Python实现
    Python数据可视化之Pygal(雷达图)
    Python数据可视化之Matplotlib(饼图)
    Python数据可视化之Matplotlib(折线图)
    控制台超市系统(Python)
  • 原文地址:https://www.cnblogs.com/wfaceboss/p/7679306.html
Copyright © 2011-2022 走看看