javascript - 防止长时间计算导致浏览器卡顿和崩溃

标签 javascript freeze web-worker

我需要检查重复的数据库名称并更改此名称以避免重复。我使用@Jefré N 建议的脚本。

function eliminateDuplicates() {

    var repeats = {};
    var error = false;

    //cache inputs
    var $inputs = $("input[type='text']");

    //loop through inputs and update repeats
    for (i = 0; i < $inputs.length; ++i) {
        //cache current element
        var cur = $inputs[i];

        //remove class
        $(cur).removeClass("double-error");

        //get text of this element
        var text = $(cur).val();

        //no text -- continue
        if (text === "") {
            continue;
            }
        //first time we've came across this value -- intialize it's counter to 1
        if ((text in repeats) === false) {
            repeats[text] = 1;
            }
        //repeat offender. Increment its counter.
        else {
            repeats[text] = repeats[text] + 1;
            }

        //update the the value for this one
        $(cur).val(text + "-" + repeats[text]);
        }

    return error; // always returns false since I'm not sure
                  // when it's supposed to return true.
    }

所以脚本工作正常,但如果我有多达一百个条目。但是如果我有几千条记录,浏览器就会卡住。 Firefox 崩溃了。如何通过添加一些加载线或一些时钟指针来防止浏览器卡住和崩溃?也许我需要使用一些 setTimeout() 函数或其他东西。请帮助防止此浏览器卡住和崩溃问题。

我试过这个:

function processLargeArrayAsync(array, fn, maxTimePerChunk, context) {
    context = context || window;
    maxTimePerChunk = maxTimePerChunk || 200;
    var index = 0;

    function now() {
        return new Date().getTime();
    }

    function doChunk() {
        var startTime = now();
        while (index < array.length && (now() - startTime) <= maxTimePerChunk) {
            // callback called with args (value, index, array)
            fn.call(context, array[index], index, array);
            ++index;
        }
        if (index < array.length) {
            // set Timeout for async iteration
            setTimeout(doChunk, 1);
        }
    }    
    doChunk();    
}

-

processLargeArrayAsync(veryLargeArray, myCallback);

没有成功。 Chrome 卡住,IE11 资源管理器也,Firefox 崩溃。怎么了? 我的记录出现在 HTML 表格中。

有些人建议使用网络 worker 。也许这里有人有实践并有一个有效的例子?

最佳答案

我认为您的代码中最麻烦的部分是 DOM 访问:获取输入值并更新它们。

根据webworkers documentation ,网络 worker 有其局限性,其中之一是 DOM 操作。所以我会放弃那个选项。

为了解决问题,我会做如下事情:

  1. 改进您的eliminateDuplicates 算法(使其更快)。
  2. 使 eliminateDuplicates 异步:将元素集分成较小的元素,并在不同的事件循环节拍 (setTimeout) 中执行每个计算。

在这里,我向您介绍我想出的解决方案。希望它能给你一些想法,帮助你解决问题。

首先,我调整了一点eliminateDuplicates(我称之为modifyDOM)

function modifyDOM(elements, repeats) {
    var input, text, i = 0;
    for (; i < elements.length; i++) {
        input = elements[i];
        text = input.value;
        // Remove class.
        input.className = input.className.replace(/\bdouble-error\b/, '');
        if (text) {
            repeats[text] = ~~repeats[text] + 1;
            input.value = text + "-" + repeats[text];
        }
    }
}

我避免在主循环中使用 jQuery,因为它的包装器使事情变得更慢,并且在您的情况下不值得使用它。这些小的变化提高了每 10.000 个元素 100 毫秒的性能(不给就给)。

我创建了两个使用 modifyDOM 的函数:一个是异步的,另一个是同步的。

function parseElementsNonBlocking(elements, maxChunkSize) {
    var repeats = {},
        nChunks = Math.floor(elements/maxChunkSize),
        i = 0,
        j = 1;

    //loop through inputs and update repeats
    for(; i < nChunks; i++, j++) {
        setTimeout(modifyDOM.bind(null, elements.slice(i, j*maxChunkSize), repeats), 0);
    }
    // Rest
    setTimeout(modifyDOM.bind(null, elements.slice(i), repeats), 0);
}

function parseElementsBlocking(elements) {
    var repeats = {};

    //loop through inputs and update repeats
    modifyDOM(elements, repeats);
}

最后,为了测试所有内容,一个函数在 DOM 准备就绪时执行并创建 10.000 个输入。然后它会输出运行上述任何方法所需的时间。

$(function () {
    var inputsDiv = $('#inputs'), i, time;
    for (i = 0; i < 10000; i++) {
        var val = i % 3 === 0 ? 'Mickey' : (i % 3 === 1 ? 'Mouse' : '');
        inputsDiv.append('<input type="text" class="double-error" name="FirstName" value="' + val + '">');
    }

    time = Date.now();
    //parseElementsBlocking($("input[type='text']"));
    parseElementsNonBlocking($("input[type='text']"), 100);
    console.log(Date.now() - time);
});

这里有 fiddle来测试这一切。

关于javascript - 防止长时间计算导致浏览器卡顿和崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39552440/

相关文章:

java - 操作完成后 Spymemcached 挂起

javascript - 在 Web Worker 中解析 XML

javascript - 如何在 Bookshelf.js 中进行嵌套插入

java - 我已经使用 java 创建了一个 portscanner,但是当我单击“执行”时,它就卡住了

javascript - 将跨度组拖放到表格上的新位置

winsock - GetQueuedCompletionStatus 挂起

javascript - 如何使用 web worker 使用 makepdf 渲染 PDF

javascript - 具有多个参数的 HTML 5 网络 worker

javascript - 如何使用 jquery 获取 div 可用的最大宽度

javascript - 应用程序中使用的类/实例方法与静态方法之间有什么显着差异吗?