XHR工厂

基本实现

  1. var AjaxHandler = new Interface('AjaxHandler', ['request', 'createXHR']);
  2. var SimpleHandler = function(){};
  3. SimpleHandler.prototype = {
  4. request: function(method, url, callback, postVars){
  5. var xhr = this.createXHR();
  6. xhr.onreadystatechange = function(){
  7. if(xhr.readyState!==4) return;
  8. (xhr.status===200)?
  9. callback.success(xhr.responseText, xhr.responseXML):
  10. callback.failure(xhr.status);
  11. };
  12. xhr.open(method, url, true);
  13. if(method !== 'POST') postVars = null;
  14. xhr.send(postVars);
  15. },
  16. createXHR: function(){
  17. var methods = [
  18. function() {return new XMLHttpRequest();},
  19. function() {return new ActiveXObject('Msxml2.XMLHTTP');},
  20. function() {return new ActiveXObject('Microsoft.XMLHTTP');}
  21. ];
  22. for(var i = 0, len=methods.length; i<len; i++){
  23. try{
  24. methods[i]();
  25. }catch (e){
  26. continue;
  27. }
  28. this.createXHR = methods[i]; //memoize the method.
  29. return methods[i];
  30. }
  31. }
  32. };

createXHR这个工厂方法根据当前的宿主环境返回适当的xhr对象.重点是createXHR在首次执行之后就被替换为了methods[i],这个就是memoizing技术了(可以称称之为记录).这样当我们下次用到createXHR的时候就不用在去能力检测了.大大的提升了性能.

SimpleHandler的调用如下:

  1. var myHandler = new SimpleHandler();
  2. var callback = {
  3. success: function(responseText){
  4. console.log('Success' + responseText);
  5. },
  6. failure: function(statusCode){
  7. console.log('Failure' + statusCode);
  8. }
  9. };
  10. myHandler.request('GET', 'stript.php', callback);

专用型连接对象

我们对上面的对象进行一个扩展,以便根据网络条件创建专门的请求对象.

首先我们先来创建两个新的处理器类:

1:QueHandler会在发起新的请求之前先确保所有请求都已经成功处理.

  1. var QueHandler = function(){
  2. this.queue = [];
  3. this.requestInProgress = false;
  4. this.retryDelay = 5;
  5. };
  6. extend(QueHandler, SimpleHandler);
  7. QueHandler.prototype.request = function(method, url, callback, postVars, override){
  8. if(this.requestInProgress && !override){
  9. this.queue.push({
  10. method: method,
  11. url: url,
  12. callback: callback,
  13. postVars: postVars
  14. });
  15. }else{
  16. this.requestInProgress = true;
  17. var xhr = this.createXHR();
  18. var that = this;
  19. xhr.onreadystatechange = function(){
  20. if(xhr.readyState !== 4) return;
  21. if(xhr.status === 200){
  22. callback.success(xhr.responseText, xhr.responseXML);
  23. that.advanceQueue();
  24. }else{
  25. callback.failure(xhr.status){
  26. setTimeout(function(){that.request(method, url, callback, postVars, true);}, that.retryDelay*1000);
  27. }
  28. }
  29. };
  30. xhr.open(method, url, true);
  31. if(method!=='POST') postVars = null;
  32. xhr.send(postVars);
  33. }
  34. };
  35. QueHandler.prototype.advanceQueue = function(){
  36. if(this.queue.length === 0){
  37. this.requestInProgress = false;
  38. return;
  39. }
  40. var req = this.queue.shift();
  41. this.request(req.method, req.url, req.callback, req.postVars, true);
  42. };

2:OffHandler会在用户处于离线状态时把请求缓存起来.

  1. var OffHandler = function(){
  2. this.storedRequests = [];
  3. };
  4. extend(OffHandler, SimpleHandler);
  5. OffHandler.prototype.request = function(method, url, callback, postVars){
  6. if(XhrManager.isOffline()){
  7. this.storedRequests.push({
  8. method:method,
  9. url:url,
  10. callback:callback,
  11. postVars:postVars
  12. });
  13. }else{
  14. this.flushStoredRequests();
  15. OffHandler.superclass.request(method, url, callback, postVars);
  16. }
  17. };
  18. OffHandler.prototype.flushStoredRequests = function(){
  19. for(var i= 0, len=this.storedRequests.length; i<len; i++){
  20. var req = this.storedRequests[i];
  21. OffHandler.superclass.request(req.method, req.url, req.callback, req.postVars);
  22. }
  23. }

在运行时选择连接对象

现在该用到工厂模式了.因为程序元根本不知道各个最终用户面临的网络条件,所以要用一个工厂在运行是选择最合适的类.

  1. var XhrManager = {
  2. createXhrHandler: function(){
  3. var xhr;
  4. if(this.isOffline()){
  5. xhr = new OffHandler();
  6. }else if(this.isHighLatency()){
  7. xhr = new QueHandler();
  8. }else{
  9. xhr = new SimpleHandler();
  10. }
  11. Interface.ensureImplements(xhr, AjaxHandler);
  12. return xhr;
  13. },
  14. isOffline: function(){ //do a quick request with SimpleHandler and see if it success.
  15. ...
  16. },
  17. isHighLatency: function(){ //do a series of requests with SimpleHandler and time the requests,Best done once, as a branching function.
  18. ...
  19. }
  20. };
  21. var myHandler = XhrManager.createXhrHandler();
  22. var callback = {};
  23. myHandler.request('GET', 'sript.php', callback);

我只想说他的isOffline的实现亮了.

XHR的三个重要属性

JS设计模式——7.工厂模式(示例-XHR)的更多相关文章

  1. JS设计模式——7.工厂模式(示例-RSS阅读器)

    RSS阅读器 由于我们只想跟RSS容器对象打交道,所以用一个工厂来实例化这些内部对象并把它们组装到一个RSS阅读器中. 使用工厂方法在好处在于,我们创建的RSS阅读器类不会与那些成员对象紧密耦合在一起 ...

  2. [JS设计模式]:工厂模式(3)

    简单工厂模式是由一个方法来决定到底要创建哪个类的实例, 而这些实例经常都拥有相同的接口. 这种模式主要用在所实例化的类型在编译期并不能确定, 而是在执行期决定的情况. 说的通俗点,就像公司茶水间的饮料 ...

  3. js设计模式:工厂模式、构造函数模式、原型模式、混合模式

    一.js面向对象程序 var o1 = new Object();     o1.name = "宾宾";     o1.sex = "男";     o1.a ...

  4. JS设计模式之工厂模式

    1 什么是工厂模式? 工厂模式是用来创建对象的一种最常用的设计模式.我们不暴露创建对象的具体逻辑,而是将将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂.工厂模式根据抽象程度的不同可以分为: ...

  5. JS设计模式--简单工厂模式

    在JS中创建对象会习惯的使用new关键字和类构造函数(也是可以用对象字面量). 工厂模式就是一种有助于消除两个类依赖性的模式. 工厂模式分为简单工厂模式和复杂工厂模式,这篇主要讲简单工厂模式. 简单工 ...

  6. JavaScript设计模式-10.工厂模式实例xhr

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. JS设计模式——7.工厂模式(概念)

    工厂模式 本章讨论两种工厂模式: 简单工厂模式 使用一个类(通常是一个单体)来生成实例. 使用场景:假设你想开几个自行车商店(创建自行车实例,组装它,清洗它,出售它),每个店都有几种型号的自行车出售. ...

  8. JavaScript设计模式--简单工厂模式例子---XHR工厂

    第一步,Ajax操作接口(目的是起一个接口检测作用) (1)引入接口文件 //定义一个静态方法来实现接口与实现类的直接检验 //静态方法不要写出Interface.prototype ,因为这是写到接 ...

  9. 设计模式——抽象工厂模式及java实现

    设计模式--抽象工厂模式及java实现 设计模式在大型软件工程中很重要,软件工程中采用了优秀的设计模式有利于代码维护,方便日后更改和添加功能. 设计模式有很多,而且也随着时间在不断增多,其中最著名的是 ...

随机推荐

  1. Mysql的两种引擎的区别

    Innodb引擎概述 Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别.该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MyS ...

  2. 使用userData兼容IE6-10,chrome,FF 及360等浏览器的本地存储

    开发过程中涉及本地存储的使用,IE很多版本都不支持localStorage,没办法,就得兼容使用userData了.废话不说了,看代码: (function(window){var LS;(funct ...

  3. JavaWeb基础【1】—— Tomcat

    此笔记是学习黑马程序员JavaWeb系列视频的课堂笔记. 感谢黑马程序员. 一.Tomcat概述 Tomcat服务器由Apache提供,开源免费.由于Sun和其他公司参与到了Tomcat的开发中,所以 ...

  4. P4417 [COCI2006-2007#2] STOL

    题目描述 米尔科买了一套别墅,他想要邀请尽量多的人和他一起庆祝.他需要一张大的木质矩形桌子来让他和他的嘉宾坐下.每张桌子可容纳的人数等于它的周长(四边长度的总和).米尔科想要买一张即可在他的公寓里放下 ...

  5. python 求两个时间差

    def timeInterval(self): today = datetime.date.today() print today modifiedTime = os.stat(filename).s ...

  6. 命令行Scp的使用----远程拷贝文件

    1.用CRT分别连上两台需要传输文件的linux系统服务器,并检查防火墙是否关闭. 查看防火墙状态: /etc/init.d/iptables status 若防火墙启用,暂时关闭防火墙: /etc/ ...

  7. 【BZOJ3105】【CQOI2013】新Nim游戏

    Description 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以选一个火柴堆拿走若干根火柴.可以只拿一根,也可以拿走整堆火柴 ...

  8. 【模板】ISAP最大流

    题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...

  9. CF600E Lomsat gelral 【线段树合并】

    题目链接 CF600E 题解 容易想到就是线段树合并,维护每个权值区间出现的最大值以及最大值位置之和即可 对于每个节点合并一下两个子节点的信息 要注意叶子节点信息的合并和非叶节点信息的合并是不一样的 ...

  10. activity 与 service 之间的通信

    activity和service通信:通过binder 举个我实际项目中的例子:在service中下载更新应用 首先是下载更新apk的service: public class UpdateVersi ...