web-dev-qa-db-ja.com

Ajax HEAD Javascript / jQuery経由のリクエスト

HEADリクエストを作成し、配列内のデータの整合性を維持する際に問題が発生しているようです。

このスニペットを考えると:

var imageTemp = Array();

$('*')
    .each(function(index){
        if($(this).css('background-image') != 'none'){
            imageTemp.Push($(this).css('background-image').slice(5, -2));
        }
    });

特定のページのすべての背景画像のURLをキャプチャします。次に、Content-LengthHEADリクエストを介して各画像のサイズを取得しようとするため、次のスニペットを使用します。

var imageData = Array();

for(var i = 0; i < imageTemp.length; i++){
    ajaxSizeRequest = $.ajax({
        type: "HEAD",
        async: true,
        url: imageTemp[i],
        success: function(message){
            imageData.Push([imageTemp[i], ajaxSizeRequest.getResponseHeader('Content-Length')]);
        }
    });
}

ただし、imageDataconsole.logを介してダンプすると、各要素(URLとコンテンツの長さを含む配列である必要があります)は[undefined, XXXX]となり、XXXXは常に最後にリクエストされたサイズですContent-Length

タイミング/スコープの問題のようですが、困惑しています。ここで一種の競合状態が発生していますか?

16
Dan Lugg

問題は、コールバック関数によってキャプチャされている単一の変数iおよびajaxSizeRequestが、コールバック関数のすべてのインスタンスで同じ変数であることです。関数を呼び出してそれにインデックス変数を渡すと、同時に、 リクエスト変数を関数自​​体にローカルにスコープします doneハンドラーの応答パラメーターを使用すると、コールバックによってキャプチャされた独立変数になるはずです。次に、各配列要素と各応答変数を正しく参照する必要があります。

var imageData = Array();

for(var i = 0; i < imageTemp.length; i++){
    updateImageData( i );
}

function updateImageData( i )
    $.ajax({
        type: "HEAD",
        async: true,
        url: imageTemp[i],
    }).done(function(message,text,jqXHR){
        imageData.Push([imageTemp[i], jqXHR.getResponseHeader('Content-Length')]);
    });
}
22
tvanfosson

iが適切に閉じ込められていないようです

さらに、ajaxSizeRequestも使用できません。これも1つの要求のみを指しているためです(おそらくループが非常に高速に実行されるため、最後の要求です)。

successコールバック関数を次のようにラップし、参照をajaxSizeRequestに変更します。

success: (function(i){
   return function(data,status,xhr){
     imageData.Push([imageTemp[i], xhr.getResponseHeader('Content-Length')]);
   };
})(i)
2
davin

あなたは私が好きなスコープにすることができます:

success: function(i){
    return function(message){
        imageData.Push([imageTemp[i], ajaxSizeRequest.getResponseHeader('Content-Length')]);
    }
}(i)
1
Josiah Ruddell

まだこれで問題があり、この投稿がすでに5年前のようなものである場合、回答のより「モダン」なバージョンをここに示します。letではなくvarを使用してください元の投稿のforループ。

情報: ES6で「var」キーワードを使用する理由はありますか? および: MDN-Let構文

0
Coffee

すべてのコールバックで共有される単一のi変数があります。
AJAXは非同期であるため、すべてのコールバックはループの終了後に実行され、すべて同じiを取得します。

これを修正するには、AJAXの呼び出しをパラメータとしてiを使用する別の関数に移動する必要があります。
したがって、各コールバックは個別のiパラメータを取得します。

0
SLaks