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. 实现细节对客户透明,可以对客户隐藏实现细节。

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

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

  • 相关阅读:
    5 Things Every Manager Should Know about Microsoft SharePoint 关于微软SharePoint每个经理应该知道的五件事
    Microsoft SharePoint 2010, is it a true Document Management System? 微软SharePoint 2010,它是真正的文档管理系统吗?
    You think you use SharePoint but you really don't 你认为你使用了SharePoint,但是实际上不是
    Introducing Document Management in SharePoint 2010 介绍SharePoint 2010中的文档管理
    Creating Your Own Document Management System With SharePoint 使用SharePoint创建你自己的文档管理系统
    MVP模式介绍
    权重初始化的选择
    机器学习中线性模型和非线性的区别
    神经网络激励函数的作用是什么
    深度学习中,交叉熵损失函数为什么优于均方差损失函数
  • 原文地址:https://www.cnblogs.com/wfaceboss/p/7679306.html
Copyright © 2011-2022 走看看