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();
})
})()
桥接模式的优点也很明显,我们只列举主要几个优点:
分离接口和实现部分,一个实现未必不变地绑定在一个接口上,抽象类(函数)的实现可以在运行时刻进行配置,一个对象甚至可以在运行时刻改变它的实现,同将抽象和实现也进行了充分的解耦,也有利于分层,从而产生更好的结构化系统。
提高可扩充性
实现细节对客户透明,可以对客户隐藏实现细节。
同时桥接模式也有自己的缺点:
大量的类将导致开发成本的增加,同时在性能方面可能也会有所减少。
我们要构建一个队列,队列里存放了很多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();
})
})()
总结:
桥接模式的优点也很明显,我们只列举主要几个优点:分离接口和实现部分,一个实现未必不变地绑定在一个接口上,抽象类(函数)的实现可以在运行时刻进行配置,一个对象甚至可以在运行时刻改变它的实现,同将抽象和实现也进行了充分的解耦,也有利于分层,从而产生更好的结构化系统。
提高可扩充性
实现细节对客户透明,可以对客户隐藏实现细节。
同时桥接模式也有自己的缺点:
大量的类将导致开发成本的增加,同时在性能方面可能也会有所减少。
相关文章推荐
- 构建XHR连接队列
- JavaScript设计模式--桥梁模式--引入
- 连接oracle数据库出现oracle ORA-12526: TNS: 监听程序: 所有适用例程都处于受限模式
- 桥梁模式
- php开发安卓服务器之 使用单例模式连接数据库
- Windows7上网共享模式二:做为无线路由器--无线网卡连接因特网,同时无线无线网卡共享
- VMware虚拟机上网络连接(network type)的三种模式--bridged、host-only、NAT
- 设计模式之桥梁模式
- VMware虚拟机上网络连接(network type)的三种模式--bridged、host-only、NAT
- javascript设计模式介绍(六)寄生构造函数模式
- Linux操作系统 内核工作队列的操作模式
- 图片式笔记:两种验证模式下的 SQL数据库连接字符串比较
- JavaScript设计模式之观察者模式(发布订阅模式)原理与实现方法示例
- 【读书笔记】读《JavaScript设计模式》之工厂模式
- 桥梁模式和适配器模式的区别
- ssh远程连接到NAT模式的虚拟机系统
- javascript设计模式系列03_策略模式做的表单验证
- 再起航,我的学习笔记之JavaScript设计模式18(观察者模式)
- 理解VMware虚拟机下网络连接的三种模式
- 理解VMWare的三种网络连接模式(bridged、NAT、host-only)