javascript对象池是什么?

JavaScript027

javascript对象池是什么?,第1张

对象池化的基本思路是:将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用,从而在一定程度上减少频繁创建对象所造成的开销。用于充当保存对象的“容器”的对象,被称为“对象池”(Object Pool,或简称Pool)。

对于没有状态的对象(例如String),在重复使用之前,无需进行任何处理;对于有状态的对象(例如StringBuffer),在重复使用之前,就需要把它们恢复到等同于刚刚生成时的状态。由于条件的限制,恢复某个对象的状态的操作不可能实现了的话,就得把这个对象抛弃,改用新创建的实例了。

并非所有对象都适合拿来池化――因为维护对象池也要造成一定开销。对生成时开销不大的对象进行池化,反而可能会出现“维护对象池的开销”大于“生成新对象的开销”,从而使性能降低的情况。但是对于生成时开销可观的对象,池化技术就是提高性能的有效策略了。

具体实现思路:

我们使用一个数组来存储已创建的xmlhttp对象实例,然后每次调用从池中去取一个实例。xmlhttp实例通讯完毕后我们不用做任何处置,因为它自身的readyState属性可以标识出它是否可用,如果当时没有空闲的xmlhttp实例,且池中的实例数小于最大实例个数,那么就创建一个新的实例并放入池中。重新改进的实现代码如下:

复制代码代码如下:

//封装XMLHTTP的MyAjaxObj类

var MyAjaxObj = new Object()

var maxXmlHttpCount = 5//最多5个xmlhttp对象存在

MyAjaxObj.reqList = []//可以清空里面的项

MyAjaxObj.getFreeObj = function() {

var req = null

var len = this.reqList.length

//先从当前的池里取

for (var i = 0i <leni++) {

if (this.reqList[i]) {

if (this.reqList[i].readyState == 4 || this.reqList[i].readyState == 0) {

req = this.reqList[i]

break

}

}

}

//如果没有闲置的对象,自己独立创建

if (req == null) {

if (this.reqList.length <maxXmlHttpCount) {

req = getXmlHttp()

this.reqList.push(req)

}

}

return req

}

//创建一个XMLHTTP对象,兼容不同的浏览器

function getXmlHttp() {

var xmlHttp = false

var arrSignatures = ["MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0",

"MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP",

"Microsoft.XMLHTTP"]

for (var i = 0i <arrSignatures.lengthi++) {

try {

xmlHttp = new ActiveXObject(arrSignatures[i])

return xmlHttp

}

catch (oError) {

xmlHttp = false//ignore

}

}

// throw new Error("MSXML is not installed on your system.")

if (!xmlHttp &&typeof XMLHttpRequest != 'undefined') {

xmlHttp = new XMLHttpRequest()

}

return xmlHttp

}

/*封装XMLHTTP向服务器发送请求的操作

url:向服务器请求的路径;method:请求的方法,即是get/post;***callback:当服务器成功返回结果时,调用的函数(类似c#回调函数)***

data:向服务器请求时附带的数据;urlencoded:url是否编码;cached:是否使用缓存; callBackError当服务器返回错误时调用的函数

*/

MyAjaxObj.send = function(url, method, callback, data, urlencoded, cached, callBackError) {

var req = this.getFreeObj()//从池里或者直接实例化一个XMLHTTP的实例

//当XMLHTTP的请求状态发生改变时调用 (核心处理函数)

req.onreadystatechange = function() {

// 当请求已经加载

if (req.readyState == 4) {

// 当请求返回成功

if (req.status == 200) { //或者 req.status <400

// 当定义了成功回调函数时,执行成功回调函数

if (callback)

callback(req, data)

}

// 当请求返回错误

else {

//当定义了失败回调函数时,执行失败回调函数

if (callBackError)

callBackError(req, data)

}

// 有池的管理,我们可以省却释放资源的方法

// try {

// delete req

// req = null

// }

// catch (e) {

// alert(e.message)

// }

}

}

//如果以POST方式回发服务器

if (method.toUpperCase() == "POST") {

req.open("POST", url, true)

//请求是否需要缓存(只有在req.open之后才可以设置此项)

if (cached)

req.setRequestHeader("If-Modified-Since", "0")

//请求需要编码

if (urlencoded)

req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')

req.send(data)

MyAjaxObj.reqList.push(req)

}

//以GET方式请求

else {

req.open("GET", url, true)

//请求是否需要缓存

if (cached)

req.setRequestHeader("If-Modified-Since", "0")

req.send(null)

MyAjaxObj.reqList.push(req)

}

return req

}

//全部清除XMLHTTP数组元素,释放资源

MyAjaxObj.clearReqList = function() {

var len = MyAjaxObj.reqList.length

for (var i = 0i <leni++) {

var req = MyAjaxObj.reqList[i]

if (req) {

try {

delete req

} catch (e) { }

}

}

MyAjaxObj.reqList = []

}

//进一步封装XMLHTTP以POST方式发送请求时的代码

//isClear:是否清除XMLHTTP数组的所有元素;其他参数的意义见 MyAjaxObj.send

MyAjaxObj.sendPost = function(url, data, callback, isClear, isCached, callBackError) {

if (isClear) {

MyAjaxObj.clearReqList()

}

MyAjaxObj.send(url, "POST", callback, data, true, isCached, callBackError)//post方法需要编码

}

//进一步封装XMLHTTP以GET方式发送请求时的代码

MyAjaxObj.sendGet = function(url, args, callback, isClear, isCached, callBackError) {

if (isClear)

MyAjaxObj.clearReqList()

return MyAjaxObj.send(url, "GET", callback, args, false, isCached, callBackError)

}

最后再ps:上周周末和一个哥们聊天的时候谈到ajax应用中的xmlhttp对象。那哥们ms很“虔诚”地问我说xmlhttp怎么就异步通信了。我当时竟然毫不思索地说因为这个对象处理我们的请求调用是“异步”的(当然可以设置成同步的,不过这是一句废话),当前这个请求不会影响其他的操作。这个回答是很“官方”的,显然没有说到问题的本质。哥们,您的眼神儿有必要那么bs人么?现在稍作分析,个人认为其实每个xmlhttp异步请求都会触发一个回调函数,这个回调函数的调用不影响其他的操作,这个方法才是“异步”。如果对比c#里的异步处理回调方法,它们在原理上其实是相通的。 哈哈,现在终于想通了, 真是太骄傲,太有出息了,想到就兴奋!

标签: javascript xmlhttp 对象池

上一篇文章写了星星生成的逻辑,详情请看 Cocos Creator开发游戏消灭星星——星星生成

星星消除是发生在用户点击之后,所以需要处理用户触摸操作。在上一篇制作星星预制时有提及,在脚本组件 starCtr.js 的start函数里监听触摸。

消除星星是消除上下左右相连的星星,所以需要根据用户点击的星星找到其他相连的星星。在Utils中增加方法needRemoveList:

现在来完成触摸处理逻辑:

通过用户点击的星星坐标找到与其相连的星星们,然后发射delete_stars事件,通知地图消除星星。关于监听和发射时间参考官方文档 监听和发射事件 。

在matrixCtr.js的onLoad方法中添加事件监听

先添加几个属性来记录消除数据

在回调函数中处理消除逻辑

上一篇 说过,动画和特效主要放在节点 ActionRoot 中处理。如图,combo特效就在combNode节点中播放。

asset、atlasAsset分别存储骨骼动画资源,combName中存储骨骼动画的名字,和资源数组一一对应,_anim是dragonBones组件。

playComb即是播放特效的方法。

combCtr是脚本组件matrixCtr中的属性,即是场景中ActionRoot节点的脚本组件。

将需要消除的星星对应的坐标清空(赋值-1)

按规则星星是一个一个消除的,所以bomb会递归调用,直到所有星星都消除。在消除星星的同时,有分数计算和动画逻辑。

星星的移除是在方法 bombStar 中处理的,在创建星星的时候使用了对象池,所以移除时把它重新放入对象池。

在移除星星的同时,伴随有星星爆炸的特效。 starParticle 是一个预制,层级很简单,在一个空节点中,添加Particle System组件和脚本组件particleCtr。

Particle System组件设置自动移除,在属性检查器中勾选 Auto Remove On Finish 选项。

我们知道一次消除星星方块越多,得分越高。

分数动画有几种:

动画在actionCtr.js中处理:

因为分数也会被频繁的创建和移除,所以也使用了对象池,分数的预制制作后面介绍。

与单个方块的分数动画一样,消除总得分动画:

层级结构很简单,都是空节点下加一个Label节点。父节点上都有一个脚本组件partScore、totalScore。

脚本也很简单,setScore方法给Label赋值。

与单个分数不同的,总得分的Label动画使用Creator的Animation编辑器制作。所以,预制中需要在节点label中添加Animation组件,在这里我们在添加一个脚本组件totalScoreLabel,这个脚本主要处理Animation动画的事件回调方法。