天天看点

为Ajax的XMLHttpRequest提供对象池(模仿Apache中ObjectPool的实现)

在网上看到了有些同志提到了为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);

}

下载: http://www.blogjava.net/Files/bennybao/pool.rar

Feedback

# re: 为Ajax的XMLHttpRequest提供对象池(模仿Apache中ObjectPool的实现) 回复 更多评论

2007-02-10 01:46 by ghf

# re: 为Ajax的XMLHttpRequest提供对象池(模仿Apache中ObjectPool的实现) 回复 更多评论

2007-02-16 11:18 by 张沈鹏

为什么要一个activePool ,没有什么用处呀,用完了直接push进入idle,用的时候直接从idle中pop,同时把xmlrequest封装一下,让他自动来pop和push,用只要给出url和recall就可以了

我的邮箱是[email protected]欢迎探讨

__reqPool={

idle:[],

new:function(){

var r=this.idle.pop();

if(!r){

if (window.XMLHttpRequest)r=new XMLHttpRequest();

else{

try{r=new ActiveXObject("Msxml2.XMLHTTP");}

catch(e){r=new ActiveXObject("Microsoft.XMLHTTP");}

}

}

return r;

}

open:function(url,recall,error){

var http=this.new();

http.open("GET",url,true);

http.onreadystatechange=function(){

if(http.readyState==4)

{

if(http.status==200)recall(http.responseText.toString());

else if(error) error(http.status,http.responseText.toString());

idle.push(http);

}

};

}

}

# re: 为Ajax的XMLHttpRequest提供对象池(模仿Apache中ObjectPool的实现)[未登录] 回复 更多评论

2007-02-16 13:57 by BennyBao

@张沈鹏

activePool确实不是必须的,但是有了activePool之后就可以很方便的知道究竟有多少已激活的Object,或者可以利用一个类似“守护线程”的定时器来监控每个Object的激活时间,以便与实现类似超时之类的功能。

另外需要说明的是,根据我的本意,这里的ObjectPool并不只为XMLHttp设计。

继续阅读