14

この質問に答えようとしているときに、奇妙な動作に遭遇しました (これは同じではありません: 彼は反復が少なすぎるためであり、私の場合は反復が多すぎるためです):

HTML:

<button id="go">it will be legend...</button>
<div id="output"></div>

JS:

var output = document.getElementById('output');
document.getElementById('go').onclick = function() {
    output.textContent += 'wait for it...';
    for (var i=0; i<3000000000; i++) {
        var unused = i; // don't really care
    }
    output.textContent += ' dary!';
};

ループは 3,000,000,000 回繰り返されるため、実行に数秒かかります。

ボタンをクリックすると、私が期待したこと:

  1. wait for it...が現れる
  2. ループのためにプロセスが少しフリーズします
  3. dary!が現れる

実際に起こったこと:

  1. ループのためにプロセスが少しフリーズします
  2. wait for it... dary!一緒に登場

なぜそのような行動をするのですか?

自分で確認してください:fiddle

4

5 に答える 5

17

その理由は、関数全体が同期的に実行されているためです。出力を に設定するまでに、wait for it...実行時間の長いループに入り、スレッドを占有します。残りを で囲むtimeoutと、最初のテキストは通常​​どおり表示されます。

var output = document.getElementById('output');
document.getElementById('go').onclick = function() {
    output.textContent += 'wait for it...';
    window.setTimeout(function() {
    for (var i=0; i<3000000000; i++) {
        var unused = i; // don't really care
    }
    output.textContent += ' dary!';
    }, 0);
};

処理中に UI がフリーズすることに注意してください。

編集: Chrome で遅延値として使用0すると機能しますが、最新の Firefox と IE 10 では機能しません。値を変更すると10、どちらの場合も機能します。

于 2013-08-20T16:10:18.273 に答える
10

Javascript はほぼシングルスレッドです。コードを実行している場合、ページは応答せず、コードが完了するまで更新されません。(これは実装固有であることに注意してください。ただし、これは現在すべてのブラウザーで行われている方法です。)

于 2013-08-20T16:08:50.633 に答える
1

コードは期待どおりに実行されています。問題は、javascript が完了するまで、ブラウザーがドキュメントへの変更を表示しないことです。タイムアウトは、コードの実行を 2 つの別々のイベントに分割することで、この問題を修正しています。次のコードは、期待したことが起こっていることを示しています。

var output = document.getElementById('output');
document.getElementById('go').onclick = function() {
    console.log('wait for it...';)
    for (var i=0; i<3000000000; i++) {
        var unused = i; // don't really care
    }
    console.log(' dary!');
};

実行が同期的でなくなるため、タイムアウト ソリューションを使用する場合も注意が必要です。

output = document.getElementById('output');
document.getElementById('go').onclick = function() {
    output.textContent += 'wait for it...';
    window.setTimeout(function() {
        for (var i = 0; i < 3000000000; i++) {
        var unused = i;
        // don't really care
        }
    output.textContent += ' dary!';
    }, 0);
    output.textContent += ' epic';
};

このバージョンを実行すると、「epic」が「dary」の前にあることがわかります。

于 2013-08-25T01:04:52.730 に答える
0

私が見る唯一の説明は、JavaScriptが実行された後にブラウザがビューを更新するということですか? 証拠として、これは期待どおりに機能します:

var output = document.getElementById('output');
document.getElementById('go').onclick = function () {
    output.textContent += 'wait for it...';
    window.setTimeout(count, 100);
};

function count() {
    for (var i = 0; i < 3000000000; i++) {
        var unused = i; // don't really care
    }
    output.textContent += ' dary!';
}
于 2013-08-20T16:15:01.330 に答える