Firefox在重for循环期间挂起

Firefox hangs during heavy for loop

本文关键字:挂起 循环 在重 for Firefox      更新时间:2023-09-26

当我的扩展开始一个繁重的工作(一个for循环,将触发更多的进程),Firefox停止响应。在我的扩展完成任务之前,它不会恢复工作。

我的扩展需要大约16000毫秒来完成它的工作。是否有一种方法来执行我的脚本异步?还是有其他办法解决这个问题?

TL;DR:是的,有一个方法。使您的代码在短迭代中运行,并使用setTimeout生成。

在JavaScript中没有线程这样的东西。好的,是的,这是Worker API。但是我仍然认为线程是不必要的和邪恶的(竞争条件,死锁,等等——这些在之前已经讨论过了)。浏览器扩展可能是JavaScript中线程可能有任何优点的唯一用例。但还是尽量避免。

。如果不是线程,那又是什么?JavaScript有一个事件循环,这是祸福参半。每次运行一段代码时,页面上的所有其他内容都会停止(这就是页面变得无响应的原因)。为了防止这种情况发生,您应该让每段代码尽可能快地运行,然后让渡给事件队列中的其他事件。

要做到这一点,将for循环替换为通过setTimeout调用自身的递归函数。所以不用这个:

var length = collection.length; // <-- 2 gazillion
var i;
for (i=0; i<length; i+=1) {
    lengthyOperation(i);
}
// Script yields here.

…您将执行如下操作:

var length = collection.length; // <-- still 2 gazillion
var i;
function lengthyOperationAsync() {
    lengthyOperation(i); // <-- still lengthy
    i += 1;
    if (i < length) {
        setTimeout(lengthyOperationAsync, 0);
    }
    // Script yields here.
}

这样,浏览器可以在冗长的for循环迭代之间更新页面并处理用户输入。只有一个缺点:在某些浏览器中,它可能需要比平时更长的时间。这是因为计时器分辨率;当使用setTimeout时,一些浏览器的最小延迟为4ms,即使您指定了0

顺便说一下,有一个名为setimmid的函数的建议,它就是为了这个确切的目的——但是大多数浏览器还没有实现它。