5

アプリが iframe 内にあり、外部ドメインから呼び出されているという問題が発生しました。IE9 は、iframe が適切に読み込まれるときに load イベントを発生させないため、setTimeout を使用してページをポーリングするのに行き詰まっていると思います。

とにかく、setTimeout が完了するまでに一般的に必要な期間を確認したいので、setTimeout がコールバックから発生する遅延をログに記録できるようにしたかったのですが、そのコンテキストをそれに渡す方法がわからないので、ログに記録します。

App.readyIE9 = function() {
  var timings = [1,250,500,750,1000,1500,2000,3000];    
  for(var i = 0; i < timings.length; i++) {
    var func = function() {
    if(App.ready_loaded) return;
      console.log(timings[i]);
      App.readyCallBack();
    };
    setTimeout(func,timings[i]);
  }
};

IE9 のコンソールで LOG: undefined が発生し続けます。

これを達成するための適切な方法は何ですか?

ありがとう

4

3 に答える 3

11

setTimeout関数が将来いつか呼び出されると、 の値はループiによってその範囲の最後まで既にインクリメントされているため、 が報告されます。forconsole.log(timings[i]);undefined

その関数で使用するiには、関数クロージャでキャプチャする必要があります。それにはいくつかの方法があります。i次のような値を取得するには、自己実行関数を使用することをお勧めします。

App.readyIE9 = function() {
  var timings = [1,250,500,750,1000,1500,2000,3000];    
  for(var i = 0; i < timings.length; i++) {
    (function(index) {
        setTimeout(function() {
            if(App.ready_loaded) return;
            console.log(timings[index]);
            App.readyCallBack();
        }, timings[index]);
    })(i);
  }
};

誰がこれを機能させるかについてのちょっとした説明として:iは、その関数の最初の引数として自己実行関数に渡されます。その最初の引数には名前が付けられindex、自己実行関数の呼び出しごとに凍結されるため、コールバックが実行されるfor前にループによって変更されることはありません。そのため、自己実行関数の内部をsetTimeout参照すると、各コールバックの配列インデックスの正しい値が取得されます。indexsetTimeout

于 2012-06-01T18:25:58.450 に答える
11

これは、 内の の値に近づいていないために発生していiますfunc。ループが終了すると、配列には存在しないi8 ( ) になります。timings.length

次のようなことをする必要があります:

App.readyIE9 = function() {
  var timings = [1,250,500,750,1000,1500,2000,3000];    
  for(var i = 0; i < timings.length; i++) {
    var func = function(x) {
      return function(){
          if(App.ready_loaded) return;
          console.log(timings[x]);
          App.readyCallBack();
      };
    };
    setTimeout(func(i),timings[i]);
  }
};
于 2012-06-01T18:25:59.453 に答える
3

setTimeoutこれは、またはsetIntervalコールバックを使用する場合によくある問題です。i関数に値を渡す必要があります。

var timings = [1, 250, 500, 750, 1000, 1500, 2000, 3000],
    func = function(i) {
        return function() {
            console.log(timings[i]);
        };
    };

for (var i = 0, len = timings.length; i < len; i++) {
    setTimeout(func(i), timings[i]);
}

デモ: http://jsfiddle.net/r56wu8es/

于 2012-06-01T18:26:00.537 に答える