1

重複の可能性: forループでsetTimeout
を使用する方法
forループでsetTimeoutを呼び出す方法

私の場合、setTimeout関数はforループ内では機能しません。すべてのforループステートメントが実行された後に実行されます。

setTimeoutjavascriptの関数の場合、このスコープの問題に直面しています。

これが私のコードスニペットです。

 ... moves[] is an array ..

 for(i=0;i<noOfMoves;i++) {

        playerName = moves[i].playerName;
        timeDiff = moves[i].timeDiff;
        console.log("Inside for loop"+ playerName);

        setTimeout(function(){
             console.log("Inside set time out :"+playerName);
        },timeDiff);
 ....
 ....
}

しかし、それは厄介に次の出力を出力します...

 Inside for loopplayer1
 Inside for loopplayer2
 Inside for loopplayer3
 Inside for loopplayer4
 .... (noOfMoeves times .. )
 Inside set time outplayer1
 Inside set time outplayer1
 Inside set time outplayer1
 Inside set time outplayer1

編集 :

私は次の方法のo/pが欲しいです

コードが1行ずつ表示されることを期待しています..最初に" "コンソールログを出力し、次に " "期間Inside for loop待機してから、" "関数コンソールログを出力します..どうすればよいですか?– </ p> timeDiffInside settimeout

 Inside for loopplayer1
 Inside set time outplayer1 // (after waiting for timeDiff time)
 Inside for loopplayer2
 Inside set time outplayer2  // (after waiting for timeDiff time)
 ......
 ......

また、playerName変数は各settimeoutコンソールログステートメントで同じ値を取得していますか?

4

3 に答える 3

2

これは完全にクロージャによるものではありません。これは、javascriptがシングルスレッドであり、javascriptが実行できる空き時間があるまでタイムアウトが設定されないためです。forループは、setTimeoutがそのコードを実行する前に常に終了します。

この問題を解決するには、次のようにすべてをsetIntervalに入れます。

var moves = [{playerName:'Test'},{playerName:'Terry'}, {playerName:'sdfsdf'}];
var currIdx = 0;
var intervalId = window.setInterval(function () {
    var playerName = moves[currIdx].playerName;
    console.log("Inside for loop"+ playerName);
    (function(name) {
        setTimeout(function(){
             console.log("Inside set time out :"+name);
        },0);
    })(playerName);
    currIdx++;
    if(currIdx >= moves.length)
        window.clearTimeout(intervalId);        
}, 10);

サンプルについてはフィドルを参照してください-http://jsfiddle.net/uTyVw/2/

于 2012-06-14T16:23:00.790 に答える
1

閉鎖のせいです。コードを次のように変更します。

for(i=0;i<noOfMoves;i++) {
    playerName = moves[i].playerName;
    console.log("Inside for loop"+ playerName);
    (function(name) {
        setTimeout(function(){
             console.log("Inside set time out :"+name);
        },timeDiff);
    })(playerName);
}

閉鎖の詳細については、こちらをご覧ください。

更新されたコード:

var moves = [
    {playerName: '1'},
    {playerName: '2'},
    {playerName: '3'},
    {playerName: '4'}
];
var timeDiff = 1000;
var currentMove = 0;

var processNextMove = function() {
    var move = moves[currentMove];
    console.log('Inside for loop: ' + move.playerName);
    currentMove++;
    window.setTimeout(function() {
        console.log('Inside set time out: ' + move.playerName);
        if(currentMove != moves.length) {
            processNextMove(); 
        }
    }, timeDiff);
};

processNextMove();
于 2012-06-14T16:18:01.063 に答える
0

反復と遅延が完了したら、次の項目に進みたいようです。そんなあなたに役立つステッパーをご紹介します。

// Generic stepper. On step will move to next item and
// run custom stepping function. If at the end will return 0.
function Stepper(stepfunc, items) {
    this.items = items;
    this.index = -1;
    this.stepfunc = stepfunc;
}

Stepper.prototype.start = function() {
    this.index = -1;
    this.step();
}

Stepper.prototype.step = function() {
    this.index++; // move to the next item

    // Stop when we reach the end.
    if (this.items.length <= this.index) {
        return 0;
    }

        /* Do something now. */
        var item = this.items[this.index];
        this.stepfunc(item);

        return 1;
}

// Custom step function.
function myStep(item) {
    // Do this now.
    console.log(item.n);

    // Get a reference to the stepper.
    var s = this;

    // Do this later.
    setTimeout(function(){
        console.log(item.n + ' after ' + item.t);
        var status = s.step();
        console.log(status);
    }, item.t);
}

var items = [{n: 'A', t: 500}, {n: 'B', t: 600}, {n: 'C', t: 1000}];
var s = new Stepper(myStep, items);
s.start();
于 2012-06-14T19:31:57.507 に答える