0

ブロブを含む配列が必要なので、私のコードは次のとおりです。

for (var i = 0; i < total; i++) {

    var xhr = createXHR();

    xhr.open('GET', 'img/tiles/' + zeroFill(i, 4) + '.png', true);
    xhr.responseType = 'blob';

    xhr.onload = function() {

        arr[i] = new Blob([this.response], {type: 'image/png'});
        // console.log(arr[i]);

    };

    xhr.send();

}

arrのi位置を出力すると、コンソールにblobが正しく表示されます(少なくとも、そのサイズが表示されます)。以前の位置を表示しようとすると、未定義になります。

すべてのXHRリクエストが完了した後でarrを見ると、コンソールには、すべての位置が未定義で最後のblobが未完了の奇妙な配列が表示されます。

4

2 に答える 2

2

これは非常によくある間違いです。ループが終了した後、onloadハンドラーは長く呼び出されます。forつまり、の値はi、ループの途中からの値ではなく、ループの最後の値になりますfor

iこれを修正するには、何らかの形式でクロージャのの正しい値をキャプチャする必要があります。それを行うにはいくつかの方法があります。

iこれは、関数の引数の値を取得する自己実行関数を使用する1つの方法です。の値は自己実行関数に渡され、ループiの反復ごとに新しいスコープが作成され、そのスコープの関数引数での正しい値が取得されます。この関数の引数は、自己実行関数の呼び出しごとに一意に存在するため、将来ハンドラーが呼び出されたときに必要になるまで、目的の値が保持されます。これがどのように見えるかです:forionload

for (var i = 0; i < total; i++) {

    var xhr = createXHR();

    xhr.open('GET', 'img/tiles/' + zeroFill(i, 4) + '.png', true);
    xhr.responseType = 'blob';

    (function(index) {
        xhr.onload = function() {

            arr[index] = new Blob([this.response], {type: 'image/png'});
            // console.log(arr[index]);
       }

    })(i);

    xhr.send();

}
于 2013-01-05T01:54:51.627 に答える
1

ajaxのすべてのコールバックは、同じi外部スコープを参照します。つまり、ajax呼び出しが完了すると、すべてのデータが同じにプッシュされiますtotal-1

補足:以前に入力されnullたインデックスは、データをより大きなインデックスにプッシュするときにJS配列がどのように機能するかを示しています。

一般的な解決策は、クロージャーを使用して、現在のi値を新しい実行コンテキストに取り込むことです。

//read comments in the numeric order
xhr.onload = (function(i) {//2. the `i` inside the function now references
                           //a new `i` independent from the outer `i`
    return function(){//3. returns a function handler that executes on xhr.onload
        arr[i] = new Blob([this.response], {type: 'image/png'});
        console.log(i); //4. logs the IIFE execution context's `i`,
                        //as it is the closest (inner-most scope chain-wise) `i`
    };
}(i)); //1. Passes outer current `i` as argument to this
       //Immediately-Invoked Function Expression (IIFE)

上記のコードの詳細については、こちらをご覧ください

于 2013-01-05T01:53:53.597 に答える