您的位置:首页 > Web前端 > JavaScript

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

2017-10-17 18:02 148 查看
针对该模式的例子现在不是很理解,写下来慢慢熟悉。

我们要构建一个队列,队列里存放了很多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();
})
})()


总结:

桥接模式的优点也很明显,我们只列举主要几个优点:
分离接口和实现部分,一个实现未必不变地绑定在一个接口上,抽象类(函数)的实现可以在运行时刻进行配置,一个对象甚至可以在运行时刻改变它的实现,同将抽象和实现也进行了充分的解耦,也有利于分层,从而产生更好的结构化系统。
提高可扩充性
实现细节对客户透明,可以对客户隐藏实现细节。

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

大量的类将导致开发成本的增加,同时在性能方面可能也会有所减少。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: