刚在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;
- }
<noscript type="text/javascript"></noscript>
上面代码中ObjectPool的构造参数poolableObjectFactory的声明如下:
代码
- // 注意: 这只是说明,不是真正的代码!
- var PoolableObjectFactory = {
- makeObject: function() {}, // 创建一个新的对象。(必须声明)
- activateObject: function(object) {}, // 当一个对象被激活时(即被借出时)触发的方法。(可选)
- passivateObject: function(object) {}, // 当一个对象被钝化时(即被归还时)触发的方法。(可选)
- destroyObject: function(object) {} // 销毁一个对象。(可选)
- };
<noscript type="text/javascript"></noscript>
结合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);
- // ......
<noscript type="text/javascript"></noscript>
最后附上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);
- }