gpt4 book ai didi

javascript - 防止 JavaScript 在大循环中锁定浏览器

转载 作者:数据小太阳 更新时间:2023-10-29 04:44:30 24 4
gpt4 key购买 nike

我有一个循环需要在浏览器中运行 2 亿次。这是几个人需要经常使用的模拟器。运行大约需要15分钟,但是在这期间,浏览器会频繁弹出“这个脚本运行时间过长”等警告,导致Firefox在运行过程中彻底挂掉。这也意味着页面不会更新我的状态指示器(这只是一个数字)。

我用谷歌搜索了“javascript yield”并阅读了前 4 页的点击率。一些人讨论了一个新的“yield”关键字,但只有一个描述和示例,我觉得难以理解,例如“包含 yield 关键字的函数是一个生成器。当你调用它时,它的形式参数绑定(bind)到实际参数,但它的主体实际上并没有被评估”。 yield 是否屈服于 UI?

我找到的为数不多的解决方案之一是这篇旧文章,它使用已弃用的被调用方参数和一个计时器来调用自身: http://www.julienlecomte.net/blog/2007/10/28/

但是,上面的示例不包含任何循环变量或状态,当我添加这些时它会分崩离析,我的最终结果始终为零。

它也不进行分块,但我发现了一些其他示例,这些示例在每次迭代时都使用“index % 100 == 0”进行分块。但是,这似乎是一种缓慢的方法。例如。这个:

How to stop intense Javascript loop from freezing the browser

但它没有任何方式来更新进度,并且不屈服于 UI(因此仍然挂起浏览器)。这是一个在执行期间挂起浏览器的测试版本:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script>
var spins = 1000000
var chunkSize = 1000;
var chunk;
function Stats() {this.a=0};
var stats = new Stats();
var big;

var index = 0;

var process = function() {
for (; index < spins; index++) {
stats.a++;
big = (big/3.6)+ big * 1.3 * big / 2.1;
console.write(big);
// Perform xml processing
if (index + 1 < spins && index % 100 == 0) {
document.getElementById("result").innerHTML = stats.a;
setTimeout(process, 5);
}
}
document.getElementById("result").innerHTML = stats.a;
};


</script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>

<body onload="process()">
<div id=result>result goes here.</div>
</body>
</html>

这是另一种尝试,stats.a 始终为零(所以我认为存在一些范围问题):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script>
var spins = 1000000
var chunkSize = 1000;
var chunk;
function Stats() {this.a=0};
var stats = new Stats();

function doIt() {
function spin() {
for (spinIx=0; (spinIx<chunkSize) && (spinIx+chunk < spins); spinIx++) {
stats.a++;
}
}

for (chunk =0; chunk < spins; chunk+=chunkSize){
setTimeout(spin, 5);
document.getElementById("result").innerHTML = stats.a;
}
document.getElementById("result").innerHTML = stats.a;
}

</script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>

<body onload="doIt()">
<div id=result>result goes here.</div>
</body>
</html>

我已经花了 48 小时试图让它工作 - 要么我很笨,要么这很难。有什么想法吗?

有几个人建议使用网络 worker 。我试了几天让他工作,但我找不到一个类似的例子来传递一个数字等。下面的代码是我最后一次尝试让它工作,但结果总是 0,而它应该是 100000。即它失败的方式与我上面的第二个示例失败的方式相同。

spinMaster.html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<script>
if(typeof(Worker)==="undefined") {
document.write("<h1>sorry, your browser doesnt support web workers, please use firefox, opera, chorme or safari</h1>");
}
var worker =new Worker("spinWorker.js");

worker.postMessage({times:1000000});

worker.onmessage=function(event){
document.getElementById("result").innerHTML=event.data;
};
</script>

<div id="result">result goes here</div>
</body>
</html>

自旋 worker .js

function State() {
this.a=0;
}

var state = new State();

self.addEventListener('message', spin, false);

function spin(e) {
var times, i;

times = e.data.times;
//times = 1000000; // this doesnt work either.

for(i;i<times;i++) {
state.a++;
}

self.postMessage(state.a);
}

结果输出:0

最佳答案

网络 worker 听起来是更好的解决方案。

我很快就写好了,所以我不知道它是否有效。性能会很差...

编辑:更改为与海报相同的格式。已测试

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script>
var spins = 1000000
var chunkSize = 1000;
var chunk;
function Stats() {this.a=0};
var stats = new Stats();
var big = 0.0;

var index = 0;

function workLoop() {

index += 1;

stats.a++;
big = (big/3.6)+ big * 1.3 * big / 2.1;
console.log(big);
// Perform xml processing
document.getElementById('result').innerHTML = stats.a;
if (index < spins) {
setTimeout(workLoop, 5);
}

}



</script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>

<body onload="workLoop()">
<div id="result">result goes here.</div>
</body>
</html>

关于javascript - 防止 JavaScript 在大循环中锁定浏览器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14063822/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com