Javascript 如何在进行密集计算时保持动画gif的运行

Javascript 如何在进行密集计算时保持动画gif的运行,javascript,browser,window,animated-gif,Javascript,Browser,Window,Animated Gif,我有一个页面,它用Javascript进行了一些密集而持久的计算。我想有一个加载动画,告诉用户正在取得进展。我现在有一个动画gif,但是当Javascript运行时,整个浏览器窗口都冻结(gif不会播放)。然后当它完成时,它就会解冻。计算必须是客户端的,因此不能在服务器上进行 有没有办法防止Javascript在计算时冻结页面和停止播放动画?如果浏览器冻结,这意味着您正在做一些严肃的工作 解决这个问题的唯一方法是在脚本执行的每秒钟增加100毫秒的睡眠时间。请查看javascriptsetInte

我有一个页面,它用Javascript进行了一些密集而持久的计算。我想有一个加载动画,告诉用户正在取得进展。我现在有一个动画gif,但是当Javascript运行时,整个浏览器窗口都冻结(gif不会播放)。然后当它完成时,它就会解冻。计算必须是客户端的,因此不能在服务器上进行


有没有办法防止Javascript在计算时冻结页面和停止播放动画?

如果浏览器冻结,这意味着您正在做一些严肃的工作


解决这个问题的唯一方法是在脚本执行的每秒钟增加100毫秒的睡眠时间。请查看javascript
setInterval()
调用。

javascript处理是单线程的,因此当代码运行时,不会运行其他动画代码


您需要将处理设置为成批运行。我不知道您正在处理什么,但是如果您正在做一些可以轻松划分的事情,那么您可以处理前N个项目,然后使用setTimeout计划在几毫秒内运行下一个块。这样,你就可以给浏览器时间去做其他需要做的事情。

你可以把工作分成小块,然后使用
setTimeout
来开始下一次迭代,一旦第一次迭代完成,浏览器就有机会更新用户界面。(这是因为浏览器只使用一个线程,因此如果它忙于执行js,就无法执行其他操作)

您还可以使用HTML5
webworkers
()在后台运行长时间运行的脚本。这就像javascript的多线程一样

它将在除IE之外的最新浏览器中工作


发现一个使用webworkers的游戏,CSS3动画通常会继续运行,即使JavaScript被阻止(使用Chrome40.0测试)

因此,您可以使用或之类的库来可视化正在进行的计算

但是,请注意CSS3动画的可用性:


您可能不再需要它了,但为了防止其他人在谷歌上搜索它,这里有另一个简单的解决方案:

*注意,只有当这个巨大的脚本执行是由一个长的迭代循环引起的时候,它才会起作用

-让你的循环像这样:

function AsyncLoop(i, lastLoop, parameters) {
        setTimeout(function () {
            if (i < lastLoop) {
                //whatever you wanna do here
                window.console.log('iteration ' + i + ': ' + parameters[i].whatevs);

                i++;
                AsyncLoop(i, lastLoop, parameters);
            }
        }, 0);
    }
这里有一个不使用参数(因此更容易理解)的小把戏,并带有一个检测所需脚本是否已完成执行的函数:


我用一个功能示例(带有简单的进度指示器)回答了这个问题


它使用“收益率”,当您只想允许其他进程使用时间片时,它的使用非常简单(并修改现有的JS循环),而且它比web workers(我也使用过)更容易设置,特别是如果您已经有一个与全局变量交互的循环。

这些密集且持久的计算是如何工作的?这是在循环中吗?@mridkash是的,它在循环中。你确定这是唯一的方法吗?是否有任何库可以做到这一点(每隔一段时间中断函数)?如果这是一个基本上需要在自己的线程中运行的算法,那么上面的Webworkers答案是唯一的选项。我不确定,但似乎是肯定的。它有一个名为
onmessage
的事件,可用于将消息传递到DOM以更新UI。@Seth更新了答案,以包含使用WebWorker的游戏链接谢谢,我认为这是唯一的方法。我在css3中使用转换作为加载程序而不是.gif,这导致css无法使用关键帧工作。所以css3也不是这个问题的解决方案。
AsyncLoop(0, incredblyLongObjectArray.length, incredblyLongObjectArray);