我想在页面上连续执行一段JavaScript代码,花费所有可用的CPU时间,但允许浏览器同时运行并具有响应性。
如果我只是连续运行我的代码,它会冻结浏览器的UI并且浏览器开始抱怨。现在我将零超时传递给setTimeout
,然后执行一小部分工作并循环回setTimeout
。这可行,但似乎没有利用所有可用的CPU。你可能会想到更好的方法吗?
更新:更具体地说,相关代码是在canvas
上不断渲染帧。这里的工作单位是一个框架。我们的目标是实现最大可能的帧速率。
答案 0 :(得分:3)
您可能想要的是集中在页面上发生的所有事情,并使用requestAnimationFrame来完成所有绘图。所以基本上你会有一个看起来像这样的函数/类(你将不得不原谅我用于Mootools类的一些样式/语法错误,只需将其作为大纲)
var Main = function(){
this.queue = [];
this.actions = {};
requestAnimationFrame(this.loop)
}
Main.prototype.loop = function(){
while (this.queue.length){
var action = this.queue.pop();
this.executeAction(e);
}
//do you rendering here
requestAnimationFrame(this.loop);
}
Main.prototype.addToQueue = function(e){
this.queue.push(e);
}
Main.prototype.addAction = function(target, event, callback){
if (this.actions[target] === void 0) this.actions[target] = {};
if (this.actions[target][event] === void 0) this.actions[target][event] = [];
this.actions[target][event].push(callback);
}
Main.prototype.executeAction = function(e){
if (this.actions[e.target]!==void 0 && this.actions[e.target][e.type]!==void 0){
for (var i=0; i<this.actions[e.target][e.type].length; i++){
this.actions[e.target][e.type](e);
}
}
}
所以基本上你会使用这个类来处理页面上发生的一切。每个事件处理程序都是onclick='Main.addToQueue(event)'
或者您想要将事件添加到页面中,只需指向将事件添加到提示中,然后使用Main.addAction将这些事件定向到您想要的任何事件做。这样,只要画布完成重绘并且再次重绘之前,每个用户操作都会立即执行。只要您的画布以合适的帧速率渲染,您的应用就应该保持响应。
编辑:忘记了requestAnimationFrame(this.loop)中的“this”
答案 1 :(得分:2)
网络工作者可以尝试
https://developer.mozilla.org/en-US/docs/DOM/Using_web_workers
答案 2 :(得分:1)
您可以通过更改每次调用所做的工作量来调整性能。在你的问题中,你说你做了“一小部分工作”。建立一个控制正在完成的工作量的参数并尝试各种值。
您可能还尝试在执行处理之前设置超时 。这样,处理所花费的时间应该计入浏览器设置的最小值。
我使用的一种技术是在处理循环计数迭代中使用计数器。然后在该函数中设置一个间隔,比如一秒,显示计数器并将其清零。这提供了一个粗略的性能值,可用于衡量您所做更改的效果。
通常,这可能非常依赖于特定的浏览器,甚至是浏览器的版本。通过可调参数和性能测量,您可以实现反馈回路以实时优化。
答案 3 :(得分:0)
可以使用window.postMessage()
来克服setTimeout
强制实施的最短时间限制。有关详细信息,请参阅this article。有一个演示here。