2

我想在页面上连续执行一段 JavaScript 代码,尽我所能花费所有可用的 CPU 时间,但同时允许浏览器正常运行和响应。

如果我只是连续运行我的代码,它会冻结浏览器的 UI 并且浏览器开始抱怨。现在我将零超时传递给setTimeout,然后它会做一小部分工作并循环回setTimeout. 这可行,但似乎并没有利用所有可用的 CPU。您可能会想到任何更好的方法吗?

更新:更具体地说,有问题的代码是canvas连续渲染帧。这里的工作单元是一帧。我们的目标是最大可能的帧速率。

4

4 回答 4

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”

于 2012-12-17T06:15:35.797 回答
2

网络工作者值得尝试

https://developer.mozilla.org/en-US/docs/DOM/Using_web_workers
于 2012-12-17T05:30:55.387 回答
1

您可以通过更改每次调用所做的工作量来调整性能。在您的问题中,您说您做了“一小部分工作”。建立一个控制正在完成的工作量的参数并尝试各种值。

您也可以尝试在处理之前设置超时。这样,处理所花费的时间应该计入浏览器设置的任何最小值。

我使用的一种技术是在我的处理循环计数迭代中有一个计数器。然后在该函数中设置一个时间间隔,比如一秒,显示计数器并将其清零。这提供了一个粗略的性能值,用于衡量您所做更改的效果。

一般来说,这可能非常依赖于特定的浏览器,甚至是浏览器的版本。通过可调参数和性能测量,您可以实现反馈循环以实时优化。

于 2012-12-17T06:39:50.490 回答
0

可以window.postMessage()用来克服强制执行的最短时间的限制setTimeout。有关详细信息,请参阅本文此处提供演示。

于 2012-12-17T08:56:12.333 回答