我需要检查重复的数据库名称并更改此名称以避免重复。我使用@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 操作。所以我会放弃那个选项。
为了解决问题,我会做如下事情:
- 改进您的
eliminateDuplicates
算法(使其更快)。 - 使
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/