是否可以增加JavaScript的超时限制?
如果我的脚本执行时间超过20/30秒,则会弹出带有不负责任页面对话框的chrome。
制作更有效的脚本对我没有帮助,因为脚本有时需要迭代一个函数达百万或十亿次
答案 0 :(得分:6)
在步骤/块上拆分功能并在setInterval(function(){})
内运行。
这样,页面将响应,您将能够通知用户执行的进度,您将完成工作。
UPDATE :这是一个简单的功能
worker
函数执行每次迭代,
chunksz
- 在单个块中运行的迭代次数
maxit
- 迭代总数。
function task(worker, chunksz, maxit)
{
var idx = 0;
var xint = null;
function exec_chunk()
{
for(var n = 0; n < chunksz; ++n)
{
if(idx >= maxit) { return; }
worker(idx++);
}
setTimeout(exec_chunk,1);
}
exec_chunk();
}
以下是一个示例:http://jsfiddle.net/Ed9wL/ 如您所见,您可以按顺序完成所有迭代。
<强> UPDATE2 强>:
假设你有一个循环:
for(var i=0; i<100000; ++i) { ... do something ... }
然后你需要将循环的主体包装成一个函数并用它来调用上面的task
:
task(function(i){ ... do something ... },100, 100000);
或者像这样:
function loopBody(i){ ... do something ... }
task(loopBody,100, 100000);
答案 1 :(得分:3)
当你有很多处理来做客户端时,你需要将你的工作分成不同的线程。浏览器只有一个线程来处理用户输入(事件)和处理JS。如果你处理太多的JS而没有屈服,那么UI会变得没有响应,并且浏览器不满意。
如何让脚本产生?新方法是使用网络工作者http://www.whatwg.org/specs/web-workers/current-work/。这可以通过创建一个单独的线程来运行你的JS,线程线程不能访问DOM并且可以同时运行。
但是,这种新技术并不存在于所有浏览器中。对于旧版浏览器,您可以通过让脚本通过超时调用自身来分解您的工作。每当发生超时时,脚本都会让浏览器运行其事件,一旦浏览器完成,您的下一次超时将被触发。
示例 http://jsfiddle.net/mendesjuan/PucXf/
var list = [];
for (var i = 0; i < 500000; i++) {
list.push(Math.random());
}
function sumOfSquares(list) {
var total = 0;
for (var i = 0; i < list.length; i++) {
total += list[i] * list[i];
// DOM manipulation to make it take longer
var node = document.createElement("div");
node.innerHTML = "Sync temp value = " + total;
document.body.appendChild(node);
}
return total;
}
function sumOfSquaresAsync(arr, callback) {
var chunkSize = 1000; // Do 1000 at a time
var arrLen = arr.length;
var index = 0;
var total = 0;
nextStep();
function nextStep() {
var step = 0;
while (step < chunkSize && index < arrLen) {
total += arr[index] * arr[index];
// DOM manipulation to make it take longer
var node = document.createElement("div");
node.innerHTML = "Async temp value = " + total;
document.body.appendChild(node);
index++;
step++;
}
if (index < arrLen) {
setTimeout(nextStep, 10);
} else {
callback(total);
}
}
}
sumOfSquaresAsync(list, function(total) {console.log("Async Result: " + total)});
//console.log("Sync result" + sumOfSquares(list));
关于jsfiddle的示例已将同步调用注释掉,您可以将其重新放入以查看浏览器的爬行情况。请注意,异步调用确实需要很长时间才能完成,但它不会导致长时间运行的脚本消息,并且它允许您在计算时与页面进行交互(选择文本,按钮悬停效果)。您可以在右下方的窗格中看到它打印部分结果。
更新 http://jsfiddle.net/mendesjuan/PucXf/8/
让我们尝试使用c-smile的任务函数来实现平方和。我认为他缺少一个参数,一个在任务完成时回调的函数。使用task
允许我们创建多个分块函数,而无需重复调用setTimeout和迭代的工作。
/**
* @param {function} worker. It is passed two values, the current array index,
* and the item at that index
* @param {array} list Items to be traversed
* @param {callback} The function to call when iteration is finished;
* @param {number} maxit The number of iterations of the loop to run
* before yielding, defaults to 1000
*/
function task(worker, list, callback, maxit)
{
maxit = maxit || 1000;
var idx = 0;
exec_chunk();
function exec_chunk()
{
for(var n = 0; n < maxit; ++n)
{
if(idx >= list.length) {
callback();
return;
}
worker(idx, list[idx]);
idx++;
}
setTimeout(exec_chunk,1);
}
}
function sumOfSquaresAsync(list, callback)
{
var total = 0;
// The function that does the adding and squaring
function squareAndAdd(index, item) {
total += item * item;
// DOM manipulation to make it take longer and to see progress
var node = document.createElement("div");
node.innerHTML = "Async temp value = " + total;
document.body.appendChild(node);
}
// Let the caller know what the result is when iteration is finished
function onFinish() {
callback(total);
}
task(squareAndAdd, list, onFinish);
}
var list = [];
for (var i = 0; i < 100000; i++) {
list.push(Math.random());
}
sumOfSquaresAsync(list, function(total) {
console.log("Sum of Squares is " + total);
})
答案 2 :(得分:3)
如果您的目标是禁止“杀死等待”消息作为慢速JavaScript的快速临时修复,则解决方案是在Google Chrome中打开工具/开发人员工具,并在浏览时将其保持打开状态并最小化桌面上的某个位置。 / p>