32

次の Javascript コードを検討してください。

function(){
    setTimeout(function() {
        $("#output").append(" one ");
    }, 1000);
    setTimeout(function() {
        $("#output").append(" two ");
    }, 1000);
}

この例はjsfiddleでも見ることができます。

#outputの値が常に"one two"その順序であると確信できますか? 通常、私はこの問題を次のように処理します。

function(){
    setTimeout(function() {
        $("#output").append(" one ");
        $("#output").append(" two ");
    }, 1000));
}

"one"しかし、サーバーからどの関数を実行するか (この例では appendまたは append ) を通知するメッセージを受け取るため、そのようにすることはできません"two"

Internet Explorer 9、Firefox 14、Chrome 20、Opera 12 でこのコードを既にテストしましたが、出力は常に でし"one two"た。

4

9 に答える 9

15

スペックはこちら

セクション 7.3のステップ 8 の私の解釈はsetTimeout、実行順序が保証されているはずだということです。

ただし、Chrome でウィンドウを最小化してから最大化すると、外部ソース (Websockets や Webworker など) からのイベントに設定されたタイムアウトが間違った順序で実行されていることがわかったため、この問題を調査しました。これはブラウザのバグであり、すぐに修正されることを願っています。

于 2013-01-25T20:21:25.633 に答える
4

あなたのフィドルでこれをいじってください

$(document).ready(function() {
    setTimeout(function() {
        $("#output").append(" one ");
    }, 1000);
});
$(document).ready(function() {
    setTimeout(function() {
        $("#output").append(" two ");
    }, 999);
});​

そして、あなたは両方が

output: one two
output: two one

可能です。したがって、スペランスキーは、タイムアウトが常に同じ順序で実行されることに依存できないということは正しいです。

タイムアウト 1000 ミリ秒が 999 ミリ秒のタイムアウトの前に実行できることを示すために、1 ミリ秒で 1 回変更したことに注意してください。

two編集:以下のコードは、前に印刷される可能性なしに実行を遅らせることができますone

function(){
    setTimeout(function() {
        $("#output").append(" one ");
       setTimeout(function() {
           $("#output").append(" two ");
       }, 100);
    }, 1000);
}
于 2012-08-02T05:47:09.943 に答える
2

はい、JavaScriptコードは単一のスレッドで実行されるため、、などのすべての非同期イベントはclick実行のmousemoveためにキューに入れられます。を呼び出すsetTimeoutと、エンジンはタイマーをキューに挿入して、少なくともdelay時間の経過後に実行します。したがって、2つsetTimeoutは2つのタイマーを次々に生成します。

JohnResigによるJavascriptタイマーのしくみをご覧ください。

于 2012-08-02T05:45:45.017 に答える
2

いいえ、確信が持てません。非同期です。

しかし実際には、ブラウザでメカニズムが実現されているため、おそらくそうなるでしょう。

于 2012-08-02T05:33:38.143 に答える
0

はい、出力は常に になります"one two"

最初のsetTimeoutは常に 2 番目の より前に実行されるためsetTimeout、遅延時間が同じ場合、最初のコールバック関数は常に 2 番目のコールバック関数の前に実行されます。

于 2012-08-02T05:36:32.807 に答える
0

イベントが同期の場合、Continuum関数を順番に実行する関数があります。

function keyedSequence(key, fn) {
  fn = fn || this;
  key.push({fn:fn});

  return function() {
    for(var i=0, n, full=1; i<key.length; i++) {
      n = key[i];
      if(n.fn == fn) {
        if(!n.called) n.called = 1, n.args = key.slice.call(arguments);
        if(!full) break
      }
      if(!n.called) full = 0
    }

    if(full) for(i=0; i<key.length; i++)
      n = key[i], key[i] = {fn:n.fn}, n.fn.apply(n, n.args);
  }
}
Function.prototype.seq = keyedSequence;

キーとして空の配列を指定します。同じキーでキー付けされた機能はグループ化されます。

window.onload = function() {
  var key = [];
  document.getElementById("test1").addEventListener('click', function1.seq(key), false);
  document.getElementById("test2").addEventListener('click', function2.seq(key), false);
}

をクリックしtest2てからクリックしても、test1実行順序はそのままです。function1function2

それを呼び出す別の方法は次のとおりです。

window.onload = function() {
  var key = [];
  document.getElementById("test1").addEventListener('click', keyedSequence(key, function1), false);
  document.getElementById("test2").addEventListener('click', keyedSequence(key, function2), false);
}
于 2012-09-13T13:48:17.723 に答える
0

更新
このメソッドでフィドルを更新しました。ここでチェックしてください

この方法はどうですか -- サーバーからやることのリストを取得します --

//Example - append one, append two
var appendList = ['one', 'two']

//then do this
appendList.forEach(function(item, index){
    setTimeout(function(){ 
        $('#output').append(item)
    }, index * 50 + 1000);
});

このようにして、順序を決定します。

于 2012-08-02T06:55:14.923 に答える