|
Posted on 2006-09-08 17:47 BennyBao 阅读(2467) 评论(3) 编辑 收藏 所属分类: AJAX
在网上看到了有些同志提到了为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
好
# 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
@张沈鹏
activePool确实不是必须的,但是有了activePool之后就可以很方便的知道究竟有多少已激活的Object,或者可以利用一个类似“守护线程”的定时器来监控每个Object的激活时间,以便与实现类似超时之类的功能。
另外需要说明的是,根据我的本意,这里的ObjectPool并不只为XMLHttp设计。
|