posts - 5, comments - 16, trackbacks - 0, articles - 0
在网上看到了有些同志提到了为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就可以了

我的邮箱是zsp007@gmail.com欢迎探讨
__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设计。

只有注册用户登录后才能发表评论。


网站导航: