剛在ajacn發(fā)了個(gè)貼,關(guān)于為XMLHttpRequest提供一個(gè)對(duì)象池。或許能幫到你,轉(zhuǎn)貼如下:
在網(wǎng)上看到了有些同志提到了為Ajax的XMLHttpRequest提供一個(gè)對(duì)象池,也讀了他們給出的實(shí)現(xiàn)代碼。感覺不是特別理想,于是模仿apache的commons中的ObjectPool的思路寫了一個(gè)簡(jiǎn)單的JavaScript版。
望指教:
代碼
function ObjectPool(poolableObjectFactory) {
this._poolableObjectFactory = poolableObjectFactory;
this._idlePool = [];
this._activePool = [];
}
// 從對(duì)象池中租借一個(gè)對(duì)象,如果目前沒有可用的空閑對(duì)象則通過poolableObjectFactory創(chuàng)建一個(gè)
// 既然是借的,用完記得一定要還哦!
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;
}
// 歸還一個(gè)對(duì)象
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);
}
}
// 返回當(dāng)前激活對(duì)象的個(gè)數(shù)
ObjectPool.prototype.getNumActive = function() {
return this._activePool.length;
}
// 返回當(dāng)前空閑對(duì)象的個(gè)數(shù)
ObjectPool.prototype.getNumIdle = function() {
return this._idlePool.length;
}
// 銷毀對(duì)象池及其中的所有對(duì)象
// 如果對(duì)象池中的對(duì)象需要析構(gòu)。那么必須實(shí)現(xiàn)poolableObjectFactory中的destroyObject方法,同時(shí)保證ObjectPool的destroy方法在需要的時(shí)候被調(diào)用到(例如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的構(gòu)造參數(shù)poolableObjectFactory的聲明如下:
代碼
// 注意: 這只是說(shuō)明,不是真正的代碼!
var PoolableObjectFactory = {
makeObject: function() {}, // 創(chuàng)建一個(gè)新的對(duì)象。(必須聲明)
activateObject: function(object) {}, // 當(dāng)一個(gè)對(duì)象被激活時(shí)(即被借出時(shí))觸發(fā)的方法。(可選)
passivateObject: function(object) {}, // 當(dāng)一個(gè)對(duì)象被鈍化時(shí)(即被歸還時(shí))觸發(fā)的方法。(可選)
destroyObject: function(object) {} // 銷毀一個(gè)對(duì)象。(可選)
};
結(jié)合XMLHttpRequest創(chuàng)建過程的簡(jiǎn)陋示例:
代碼
// 聲明XMLHttpRequest的創(chuàng)建工廠
var factory = {
makeObject: function() {
// 創(chuàng)建XMLHttpRequset對(duì)象
// 注:這里的創(chuàng)建方法不夠強(qiáng)壯,勿學(xué)!
if (window.ActiveXObject){
return new ActiveXObject("Microsoft.XMLHTTP");
}
else {
return new XMLHttpRequest();
}
},
passivateObject: function(xhr) {
// 重置XMLHttpRequset對(duì)象
xhr.onreadystatechange = {};
xhr.abort();
}
};
var pool = new ObjectPool(factory); // 創(chuàng)建對(duì)象池
// ......
var xhr = pool.borrowObject(); // 獲得一個(gè)XMLHttpRequest對(duì)象
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// ......
pool.returnObject(xhr); // 歸還XMLHttpRequest對(duì)象
}
};
xhr.open(method, url, true);
// ......
最后附上jsUnit的測(cè)試用例:
代碼
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);
}