一页面多XMLHttpRequest对象

  刚在ajacn发了个贴,关于为XMLHttpRequest提供一个对象池。或许能帮到你,转贴如下:

  在网上看到了有些同志提到了为Ajax的XMLHttpRequest提供一个对象池,也读了他们给出的实现代码。感觉不是特别理想,于是模仿apache的commons中的ObjectPool的思路写了一个简单的JavaScript版。

  望指教:

  代码

  function ObjectPool(poolableObjectFactory) {

  this._poolableObjectFactory = poolableObjectFactory;

  this._idlePool = [];

  this._activePool = [];

  }

  // 从对象池中租借一个对象,如果目前没有可用的空闲对象则通过poolableObjectFactory创建一个

  // 既然是借的,用完记得一定要还哦!

  ObjectPool.prototype.borrowObject = function() {

  var object = null;

  var idlePool = this._idlePool;

  var factory = this._poolableObjectFactory;

  if (idlePool.length > 0) {

  object = idlePool.pop();

  }

  else {

  object = factory.makeObject();

  }

  if (object != null) {

  this._activePool.push(object);

  if (factory.activateObject) {

  factory.activateObject(object);

  }

  }

  return object;

  }

  // 归还一个对象

  ObjectPool.prototype.returnObject = function(object) {

  function indexOf(array, object) {

  for (var i = 0; i < array.length; i++) {

  if (array[i] == object) return i;

  }

  return -1;

  }

  if (object != null) {

  var activePool = this._activePool;

  var factory = this._poolableObjectFactory;

  var i = indexOf(activePool, object);

  if (i < 0) return;

  if (factory.passivateObject) {

  factory.passivateObject(object);

  }

  activePool.splice(i, 1);

  this._idlePool.push(object);

  }

  }

  // 返回当前激活对象的个数

  ObjectPool.prototype.getNumActive = function() {

  return this._activePool.length;

  }

  // 返回当前空闲对象的个数

  ObjectPool.prototype.getNumIdle = function() {

  return this._idlePool.length;

  }

  // 销毁对象池及其中的所有对象

  // 如果对象池中的对象需要析构。那么必须实现poolableObjectFactory中的destroyObject方法,同时保证ObjectPool的destroy方法在需要的时候被调用到(例如Window的unload事件中)。

  ObjectPool.prototype.destroy = function() {

  var factory = this._poolableObjectFactory;

  function returnObject(object) {

  if (factory.passivateObject) {

  factory.passivateObject(object);

  }

  }

  function destroyObject(object) {

  if (factory.destroyObject) {

  factory.destroyObject(object);

  }

  }

  var activePool = this._activePool;

  for (var i = 0; i < activePool.length; i++) {

  var object = activePool[i];

  returnObject(object);

  destroyObject(object);

  }

  var idlePool = this._idlePool;

  for (var i = 0; i < idlePool.length; i++) {

  var object = idlePool[i];

  destroyObject(object);

  }

  this._idlePool = null;

  this._activePool = null;

  this._poolableObjectFactory = null;

  }

  上面代码中ObjectPool的构造参数poolableObjectFactory的声明如下:

  代码

  // 注意: 这只是说明,不是真正的代码!

  var PoolableObjectFactory = {

  makeObject: function() {}, // 创建一个新的对象。(必须声明)

  activateObject: function(object) {}, // 当一个对象被激活时(即被借出时)触发的方法。(可选)

  passivateObject: function(object) {}, // 当一个对象被钝化时(即被归还时)触发的方法。(可选)

  destroyObject: function(object) {} // 销毁一个对象。(可选)

  };

  结合XMLHttpRequest创建过程的简陋示例:

  代码

  // 声明XMLHttpRequest的创建工厂

  var factory = {

  makeObject: function() {

  // 创建XMLHttpRequset对象

  // 注:这里的创建方法不够强壮,勿学!

  if (window.ActiveXObject){

  return new ActiveXObject("Microsoft.XMLHTTP");

  }

  else {

  return new XMLHttpRequest();

  }

  },

  passivateObject: function(xhr) {

  // 重置XMLHttpRequset对象

  xhr.onreadystatechange = {};

  xhr.abort();

  }

  };

  var pool = new ObjectPool(factory); // 创建对象池

  // ......

  var xhr = pool.borrowObject(); // 获得一个XMLHttpRequest对象

  xhr.onreadystatechange = function() {

  if (xhr.readyState == 4) {

  // ......

  pool.returnObject(xhr); // 归还XMLHttpRequest对象

  }

  };

  xhr.open(method, url, true);

  // ......

  最后附上jsUnit的测试用例:

  代码

  function test_pool() {

  var factory = {

  counter: 0,

  makeObject: function() {

  return {id: ++ this.counter};

  },

  activateObject: function(object) {

  object.activated = true;

  },

  passivateObject: function(object) {

  object.activated = false;

  },

  destroyObject: function(object) {

  object.destroyed = true;

  }

  };

  var pool = new ObjectPool(factory);

  // borrowObject object1

  var object1 = pool.borrowObject();

  assertEquals(object1.id, 1);

  assertTrue(object1.activated);

  assertEquals(factory.counter, 1);

  assertEquals(pool.getNumActive(), 1);

  assertEquals(pool.getNumIdle(), 0);

  // borrowObject object2

  var object2 = pool.borrowObject();

  assertEquals(object2.id, 2);

  assertTrue(object2.activated);

  assertEquals(factory.counter, 2);

  assertEquals(pool.getNumActive(), 2);

  assertEquals(pool.getNumIdle(), 0);

  // borrowObject object3

  var object3 = pool.borrowObject();

  assertEquals(object3.id, 3);

  assertTrue(object3.activated);

  assertEquals(factory.counter, 3);

  assertEquals(pool.getNumActive(), 3);

  assertEquals(pool.getNumIdle(), 0);

  // returnObject object2

  pool.returnObject(object2);

  assertFalse(object2.activated);

  assertEquals(factory.counter, 3);

  assertEquals(pool.getNumActive(), 2);

  assertEquals(pool.getNumIdle(), 1);

  // returnObject object3

  pool.returnObject(object3);

  assertFalse(object3.activated);

  assertEquals(pool.getNumActive(), 1);

  assertEquals(pool.getNumIdle(), 2);

  // returnObject object1

  pool.returnObject(object1);

  assertFalse(object1.activated);

  assertEquals(pool.getNumActive(), 0);

  assertEquals(pool.getNumIdle(), 3);

  // destroy the pool

  pool.destroy();

  assertTrue(object1.destroyed);

  assertTrue(object2.destroyed);

  assertTrue(object3.destroyed);

  }