ブラウザで 2 億回実行する必要があるループがあります。複数の人が定期的に使用する必要があるシミュレーターです。実行には約 15 分かかりますが、この間、ブラウザは「このスクリプトは時間がかかりすぎています」などの警告を頻繁にポップアップ表示し、機能中に Firefox を完全にハングさせます。これは、ページがステータス インジケーター (単なる数字) を更新しないことも意味します。
「javascript yield」をグーグルで検索し、ヒットの最初の 4 ページを読みました。新しい「yield」キーワードについて議論する人もいますが、説明と例が 1 つしかなく、理解できないと思います。たとえば、「yield キーワードを含む関数はジェネレーターです。呼び出すと、仮パラメーターは実引数にバインドされますが、体は実際には評価されません」。yield
UI に屈しますか?
私が見つけたいくつかの解決策の 1 つは、非推奨の callee 引数とタイマーを使用して自分自身を呼び出すこの古い投稿です: http://www.julienlecomte.net/blog/2007/10/28/
ただし、上記の例にはループ変数や状態が含まれていません。これらを追加するとバラバラになり、最終的な結果は常にゼロになります。
チャンクも行いませんが、反復ごとに「index % 100 == 0」を使用してチャンクする他の例をいくつか見つけました。ただし、これは遅い方法のようです。例:
激しい Javascript ループでブラウザがフリーズするのを防ぐ方法
しかし、進行状況を更新する方法がなく、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 時間費やしました。何か案は?
何人かの人々が Web ワーカーを提案しています。私は彼が機能するように数日間試みましたが、数値などを渡す同様の例を見つけることができませんでした.以下のコードは、それを機能させるための私の最後の試みでしたが、結果は常に 0 です 100000.つまり、失敗します上記の 2 番目の例が失敗するのと同じように。
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>
spinWorker.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