0

次のように呼び出される 3 つの関数があります。

<body onLoad="startIt(),mssTmt(),timeout()">

彼らです:

function startIt(){
    document.write('Timeout has started!');
}
function timeout(){
    function sleep(milliSeconds) {
        var startTime = new Date().getTime();
        var cnt=0;
        while (new Date().getTime() < startTime + milliSeconds){
            cnt++;
            if(cnt%1000000==0)
                console.log('time expired: '+(new Date().getTime())+'<br>');
        }
    }
    sleep(3000);
}
function mssTmt(){
    var greeting = 'Hello, I am awake!';
    document.write('<hr>'+greeting);
}

だから私は次のことを期待していました:

  1. 「Timeout has started!」と書かれます。ページが読み込まれた直後にページに表示されます。
  2. 次に「こんにちは、私は起きています!」と書かれます。
  3. そして、関数 timeout のループ内で生成されたログがコンソールに順次出力されます。しかし、そのようなものは何もありません。実際には、最初に来るのは関数 timeout() のループです。そのため、これらすべてのログ メッセージを確認した、ページに記述された関数 startIt() および mssTmt() でメッセージを取得します。私はこれが私にとって異常に見えることを告白しなければなりません. なぜそのようなシーケンスですか?私にはいくつかの推測がありますが、もちろん、実際の JS の第一人者から正確な説明を得る方がずっと良いでしょう! ぷっすっ!

RoryKoeheinの回答後に更新されました。彼がリンクでくれたものを読みましたが、理解できないことがいくつかあります。

コードを少し変更しました。今、呼び出し元があります:

function getStarted(){
    console.log(new Date().getTime()+' > getStarted() has been called');
  try{
    startIt();
    mssTmt();
timeout();
  }catch(e){
    alert(e.message);
  }
}

…</p>

<a href="javascript:void();" onclick="getStarted();" id="getstarted">Get started!</a>

その代わり

<body onLoad="startIt(),mssTmt(),timeout()"> 

すべての関数が呼び出される直前に alert() を追加すると、シーケンスはコードに配置されたものとまったく同じになります - startIt()、mssTmt()、timeout()。アラート ポップアップをクリックするまで、すべての実装がブロックされます。イラストをご覧ください。アラートを削除すると、以前と同じように機能します (質問の開始点を参照してください)。では、アラートがすべてのプロセスをブロックする場合、なぜ実装 (i/o) の順序を変更するのでしょうか? 次に、関数 timeout() を setTimeout(); 経由で呼び出そうとすると、奇妙なスクリプトの動作に気付きました。ここ: http://javascript.info/tutorial/events-and-timing-depth#the-settimeout-func-0-tricksetTimeout(.., 0) トリックは、スタックされたイベントの後にコードを実行し、タイミング関連の問題を修正するために使用されます。次のようにコードを変更すると: setTimeout(timeout,[delay]); それは常に予測不可能に進行します:

  • 遅延を0に設定すると、関数timeout()のループが完了した後にのみ出力されます
  • 遅延を増やすと、出力 (startIt(),mssTmt()) が BEFORE ループになることもあれば、遅延値に応じて後で出力されることもあります。

しかし、最も奇妙なことは、同じ遅延値であっても、すべての試行中に I/O の順序が異なることです! 例: setTimeout(timeout,3); 関数 startIt()、mssTmt() で最初に出力が発生する場合もあれば、逆の場合もあります – timeout()。正直言って意味が分かりません…

4

1 に答える 1