前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >JavaScript设计模式--桥梁模式--XHR连接队列

JavaScript设计模式--桥梁模式--XHR连接队列

作者头像
wfaceboss
发布于 2019-04-08 02:55:26
发布于 2019-04-08 02:55:26
73100
代码可运行
举报
文章被收录于专栏:wfacebosswfaceboss
运行总次数:0
代码可运行

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*
* 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)建立一个简单的观察者模式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*
*一个简答简单的观察者模式
* */
(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. 实现细节对客户透明,可以对客户隐藏实现细节。

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-10-16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
博主你好 求告知文件密码
博主你好 求告知文件密码
回复回复点赞举报
推荐阅读
android activitymanagerservice_安卓开发API
Android中Java层的ActivityManager类中封装了很多API,可以供我们查询当前系统的很多信息,包括:内存、进程(Process)、任务栈(Task)、服务(Service)等的相关信息。
全栈程序员站长
2022/10/04
4580
安卓学习之-ActivityManager
获取方法 ActivityManager mActivityManager (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
全栈程序员站长
2022/10/04
6450
android activitymanager 系统api_Android view
ActivityManager服务是对Activity管理、运行时功能管理和运行时数据结构的封装,进程(Process)、应用程序/包、服务(Service)、任务(Task)信息等。包括以下功能:
全栈程序员站长
2022/10/04
5910
android activitymanager 系统api_Android view
基于android的_android studio创建activity
Android 如何判断一个应用在运行 在一个应用中,或一个Service 、Receiver中判断一个应用是否正在运行,以便进行一些相关的处理。 这个时候我们需要得到一个ActivityManager,这个Manager顾名思意就是管理Activity的,它有一个方法叫getRunningTasks,可以得到当前系统正在运行的Task的列表,代码如下: ActivityManager am = (ActivityManager)context.getSystemService(Context.
全栈程序员站长
2022/10/04
8500
ActivityManager 管理Activity[通俗易懂]
参考:https://www.jianshu.com/p/063fae89206b https://blog.csdn.net/qq_38520096/article/details/82109948 https://blog.csdn.net/lanye11/article/details/52221359
全栈程序员站长
2022/10/04
7130
android进程 清理及activity栈管理
MainActivity如下: package come.on;   import android.app.Activity;   import android.content.Context;   import android.content.Intent;   import android.os.Bundle;   import android.view.View;   import android.view.View.OnClickListener;   import android.widget
xiangzhihong
2018/01/29
1.5K0
activity详解_activity教程
Activity可以获取运行中的应用信息,可以获取到servcie,process,app,memory,Task信息等。
全栈程序员站长
2022/10/04
1.1K0
Android中ActivityManager学习笔记(1)-MemoryInfo「建议收藏」
与系统中所有的Activity进行交互的类。官网一句话解释了这个东西,但是有点随意了。ActivityManager的作用很多,我们通过它获得内存信息,进程信息,还可以终止某个进程。当然啦,只能终止用户的进程,系统的进程是杀死不了的。下面我通过实例,一步一步学习它的具体作用,我也是刚学,不能从宏观的角度给大家解释清楚它的具体作用。希望通过程序一步一步的写下去,其每个方法的作用也就清楚了,从而我们就知道它能干什么啦。语言组织能力差,所以就用代码来解释吧。
全栈程序员站长
2022/10/29
7760
Android中ActivityManager学习笔记(1)-MemoryInfo「建议收藏」
Android ActivityManager
ActivityManager虽然名为Activity管理器,其实际功能比类名描述的广泛,定义的方法涵盖了内存、进程、任务、设备等相关功能。因此,将ActivityManager理解为AppManager,更符合这个类。
大公爵
2022/11/02
6890
Android检测Activity或者Service是否运行
需求:假设我们的APP有3个页面AActivity,BActivity,CActivity,我们的APP需要一直运行在前台(特殊设备),要求实现一个监控服务,来监视APP是否运行,如果有3个页面都不运行了就说明这个APP已经挂掉了,否则说明APP在运行状态,不做处理,挂掉之后,我们需要重新启动App来让它继续处理运行状态,对外暴露一个来停止监控服务的广播,这样我们想停止监控服务时,发送一个广播即可。
程序员飞飞
2020/02/27
2.7K0
任务管理器(ActivityManager)
任务管理器(ActivityManager) Android中ActivityManager类似于Windows下的任务管理器,能得到正在运行程序的内容等信息 List getRunningServices(int maxNum) Return a list of the services that are currently running. 这个maxNum是指返回的这个集合的最大值 可以利用ActivityManager去判断当前某个服务是否正在运行。 List getRunni
xiangzhihong
2018/01/26
2.2K0
Android 点击通知栏消息打开activity,并判断app是否运行
android的通知栏消息点击事件如果是打开一个activity时,我们要考虑两种情况:
程思扬
2022/01/10
3.5K0
【Android】如何知道某个Activity是否在前台?
转载自zrong's blog 有一个Android应用包含包含一个后台程序,该程序会定期连接服务器来实现自定义信息的推送。但是,当这个应用处于前台的时候,后台程序就没有必要连接服务器了。这样可以节省网络资源,也更省电。 用什么方法知道该应用是否处于前台呢? 网上搜到的方法大多数都是使用下面的代码: ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE); //获得task列表 List<ActivityM
Gavin-ZYX
2018/05/18
1.6K0
满足合规的关于“只在应用主进程”中做初始化操作的判断逻辑
package com.tencent.qcloud.tim.demo; import android.app.ActivityManager; import android.content.Context; import android.util.Log; import java.util.List; public class SessionWrapper { private static final String TAG = SessionWrapper.class.getSimpleNa
Junker
2022/02/18
6250
Android获取Activity(应用)的执行状态及其它信息[通俗易懂]
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/116351.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/07
9560
Delphi类型和引用
概要介绍: 类类型和下面要讲到的类引用类型是一种特殊的数据类型,是Object Pascal面向对象编程的基础。  一:类类型概述 和以前介绍的几种数据类型相比,类类型具有如下特点: 类类型的成员可以是不同的数据类型,这一点跟记录类型相似,因此,类类型首先是由不同的字段 组成的。 类类型除了包含数据以外,还包含了操纵数据的方法及特性。类类型把数据和方法封装在一起。 类类型具有可继承性,所谓继承就是一个新的类类型,不必什么都从新定义,只需要继承一个已有 的类型再加上自己的成员就构成一个新的类类型。事实上Delphi中所有的元件都是从一些共同的祖先类 继承下来的,利用类的可继承性,您可以编写您自己的类元件,并把它加到Delphi的环境中去。 被继承的类我们称为基类,继承下来的类我们称为派生类,基类的成员自动成为派生类的成员。类 的继承具有传递性,例如假设T3继承了T2,而T2又是继承了T1,可以认为T3也继承T1。在Delphi中,所 有的类都是从一个共同的类TObject继承下来的,TObject类的声明在System单元中,它定义了一些操纵 类的最基本的方法,因此,Tobject也被称为缺省祖先类。 TObject是一个抽象类,它的派生类可以对TObject中的方法重载,包括对它的构造 Create 和析构 Destory的重载。 二:类类型的声明 类类型的声明比较复杂,其语法如下: Type 类=class(基类) [成员列表] End; 从以上语法可以看出,类类型可以指定一个祖先类型,表示该类型是从这个基类继承下来,如: Type TClass=Class(TObject) 这个例子,声明了一个名叫TClass的类类型,它是从类TObject继承下来的。注意,在Delphi中,类 名一般都是以T打头,以区别于其它数据类型。如果省略了指定基类,则表明直接从TObject继承下来。 成员列表的定义是这样 字段定义 方法定义 属性定义 类类型可以有三类成员分别是字段、方法、特性。字段的声明类型于记录类型中字段的声明,类类 型中的方法又可以分为4类,分别是构造、析构、过程和函数。分别用 Constructor、 Destructor、 Procedure、Function这4个保留字声明,类类型中的特性用保留字Property来声明,一个典型的类类型 示例如下: Type TClass=Class Private FX,FY,FZ:Integer; FS:String[128]; Public Constructor Create(X,Y,Z:Integer;S:string); Destrutor Destroy;override; Procedure Display;Virtual; Function SetStr(const Value:string); Publish Property Caption:String read FS Write SetStr; End; 上例中,声明了4个字段,数据类型分别是Integer和String。在Delphi中,一般私有变量字段都以 F打头。并且声明了一个构造CREATE,一个析构Destroy,一个过程Display,一个函数SetStr。另外还声 明了一个属性Caption。其它的语法元素如Private、Public等将在后面介绍。 注意:跟其它数据类型不同的是,类类型的声明只能出现在程序的Type区,而其它数据类型则可以 在Var区或过程或函数或方法的Begin语句之前声明。因此类类型的作用域总是全局的。 顺便提一下,类类型包括包含类类型分量的构造类型不能作为文件类型的基类型。 三:类类型的字段 类类型中的字段也就是类的数据部分,其声明方法同记录中字段的声明语法相似: 标识符:类型 其中字段的类型可以是各种数据类型,甚至是另一个类类型。 要访问对象的某个字段,跟访问记录变量中的字段类似,是用对象名加小圆点和字段名。 四:类类型的方法 类类型中的方法是个特定的名称,从形式上看也不过是一些过程或函数,不同的是方法是在类类型内部 声明的并只操纵类本身,因此在Object Pascal中方法有其特定含义。我们姑且都称它为方法。 方法的声明和定义 方法定义 方法首部;方法指示字 方法的声明跟变通的过程或函数的声明既相似也有不同的地方,相似的是声明时只需写出方法的首 部,不同的是声明方法时可以加上方法指示字。 方法分为4种
Vaccae
2019/07/24
2.6K0
Delphi使用NativeXml处理XML(二)
4.1.类(Classes) 4.1.1.TComponentAccess类   TComponentAccess = class(TComponent) 4.1.1.1.ComponentState   property ComponentState; 4.1.1.2.SetComponentState   procedure SetComponentState(const AState: TComponentState); 4.1.2.TNativeXml类   TNativeXml = class(TPersistent)   TNativeXml是XML文件的载体。创建一个TNativeXml,然后使用方法LoadFromFile、LoadFromStream或ReadFromString加载XML文档到内存中。或者从头开始使用Root.NodeNew添加节点,并最终SaveToFile和SaveToStream保存结果为一个XML文档。用属性Xmlformat = xfReadable确保缩进(易读)输出。 4.1.2.1.AbortParsing   property AbortParsing: boolean;   如果您使用一个SAX-like方式的OnNodeNew和OnNodeLoaded事件,并要中止解析过程,设置AbortParsing为True。例如:
Vaccae
2019/07/25
1.5K0
Android开发笔记(七十九)资源与权限校验
因为移动设备的硬件配置各不相同,为了防止使用了不存在的设备资源,所以要对设备的硬件情况进行检查。一般情况下,前置摄像头、部分传感器在低端手机上是没有的,像SD卡也可能因为用户没插卡使得找不到SD卡资源。下面是校验这些硬件设备的说明:
aqi00
2019/01/18
5900
delphi使用bcb的c++ .obj .o,lazarus x64内联汇编,att和intel
The {$ASMMODE XXX} directive informs the compiler what kind of assembler it can expect in an asm block. The XXX should be replaced by one of the following:
战神伽罗
2019/07/24
3.5K0
delphi使用bcb的c++ .obj .o,lazarus x64内联汇编,att和intel
Android开发笔记(八十)运行状态检查
大家都知道刻舟求剑的寓言故事,说的是事物是发展变化着的,如果拘泥于原来的情况,那随着情况的改变,就不会得到预期的结果。同样,影响app运行的因素,并不只是外部环境(如硬件、系统、权限等等),还包括app自身的运行信息。如果app的运行状态发生了变化,那么原先处理正确的逻辑也可能处理失败,所以在特定的情况下,我们得对app的运行情况进行检查。
aqi00
2019/01/18
6360
相关推荐
android activitymanagerservice_安卓开发API
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档