1

次のコードがあります。

for (var i = 0; i < numFiles; i++) {
    $.post('/Secure/File/PhysicalFileHandler.ashx?custId=whatever&idx=' + i, function (data) {
        ids += data + '|';
        if (i == numFiles-1) {
            ids = ids.substring(0, ids.length - 1);
        }
    });

}

最後の投稿が完了した後にコードのチャンクを実行するにはどうすればよいですか? 上記で試していた方法は機能しません(iそこに到達==numFilesた時点ですでに機能しています)。提案?

4

2 に答える 2

2

これはやや一般的な問題です。参照している「i」は for 関数によって処理され、通常、コールバックがトリガーされるまでに for 関数の実行が終了しています (この場合、「i」は既に numFiles に等しいです)。 )。これにはいくつかの解決策があります。1 つは、コールバックを次のように変更することです。

(function (i) {
  return function (data) {
    ids += data + '|';
    if (i == numFiles-1) {
        ids = ids.substring(0, ids.length - 1);
    }
})(i)

これが行うことは、ループの実行ごとに新しい関数を作成し、関数が「i」への独自の参照を持つたびに、for ループの定義/i の値を振り返る代わりに、独自のローカル パラメーターを持っていることです。参照する。コールバックがトリガーされたときに正しい値が保持されるように、for ループの最初のパス中にコードを実行する必要があるため、これは別の関数を返すことによって行う必要があります。

もう 1 つの方法は、post ステートメント全体を i の独自のコピーで関数にラップすることです。この 2 つの間に大きな違いはないと思います。個人的には、コードの全体的なフローの影響を最小限に抑えるため、上記のスニペットのアプローチをより好みますが、これについては意見が分かれます。

于 2013-01-05T01:39:33.097 に答える
0

投稿は開始された順序で終了しない場合があります。すべてが終了したことを知るには、終了するたびにカウントする必要があります。

var finishedCount = 0; // track number of calls finished
for (var i = 0; i < numFiles; i++) {
    (function(i) {
        $.post('/Secure/File/PhysicalFileHandler.ashx?custId=whatever&idx=' + i, function (data) {
            ids += data + '|';
            finishedCount = finishedCount + 1; // increment number of calls finished
            if (finishedCount == numFiles) { // run only when all calls have finished
                ids = ids.substring(0, ids.length - 1);
            }
        });
    })(i); // capture value of i in closure
}

編集: このバージョンではポスト コールバック関数で i が使用されていないため、クロージャで i の値をキャプチャする必要はなくなりました。

于 2013-01-05T06:22:25.983 に答える