5

これは、AJAX の機能に関する私の誤解である可能性がありますが、GET 要求が実際に終了する前に$.getコールバック ( .always()) が呼び出される状況があります。少なくとも、そのように見えます。

コード

var apiRequest  = 'some/url/';

// fetch list of video embed codes
$.get( apiRequest, function( embed_codes ) {

    // added this per Explosion Pills' answer
    var jqxhrs = [];

    // for each embed code, get video details (name, duration, etc.)
    for ( var i = 0; i < embed_codes.length; i++ ) {
        var videoDetailsRequest = '/v2/assets/' + embed_codes[i];
        //..declare vars..

        // fetch video details
        var jqxhr = $.get( videoDetailsRequest, function( video ) {
            // build playlist entry for each video
            playlistItem = '<li><h3>' + video.name + '</h3><p>' + video.description + '</p></li>';

            // create object of video HTML, with key = "video name" for sorting later
            videoArray[video.name] = playlistItem;
        }, 'jsonp' )

        // added this per Explosion Pills' answer
        jqxhrs.push( jqxhr );
    }

    // updated from jqxhr.always( function() {
    $.when( jqxhrs ).always( function() {
        // create array of keys
        for ( k in videoArray ) {
            if ( videoArray.hasOwnProperty( k ) ) { keys.push( k ); }
        }

        // append alphabetized list of videos to the page...
    });
}, 'jsonp' );

コードの機能

基本的に、コードはこれを行います: ビデオ埋め込みコードのリストをループします。ループの反復ごとに、for各ビデオの詳細をフェッチし、それらの詳細を多次元配列にプッシュします。すべての動画の取得が完了したら、.always()コールバックを呼び出します。これにより、動画がアルファベット順の再生リストに並べ替えられ、ページに追加されます。

問題

.always()コールバックは、すべての動画が取得される前に呼び出されることがあります。プレイリストには 9 つのビデオがありますが、コールバックが発生する前に 6 つまたは 7 つしか返されないことがあります。これは、私のプレイリストが少し短いことを意味します。キーの数を alert() し、コンソールを使用して、これをテストしました。私が見たのは、6 ~ 7 個のビデオが返さalert()コールバックで が発生し残りのビデオが返されるということです。

私の質問:

なぜこうなった?AJAX リクエストが完了した.always()にコールバックが発生したと思いました。これは、コールバックが発生する前にすべてのビデオを返さなければならないということではないでしょうか? AJAX の「A」に関係していると思われますが、コールバックの目的はこれを説明することだと思いました。私が理解するのを助けるものは何でも大歓迎です。ありがとう!always()

4

1 に答える 1

6

これを設定した方法では、ループ内の最後のajaxリクエストが完了する.alwaysとすぐにコールバックが起動します。これは、他の人に対して順不同で発生する可能性があります。ループ内のすべてのリクエストが完了したとき、または外部リクエストが完了したときに起動するかどうかはわかりません。

外側のリクエストについては、簡単です。呼び出しをチェーンするだけです.always(または.done、それらは同じであり、後者が好ましいと思います)。

他のすべてのajaxリクエストが完了したときに完了させたい場合は、を使用できます。これは、すべての遅延オブジェクトが完了し$.whenたときにチェックします。

var jqxhrs = [];
   ...for loop...
   var jqxhr = $.get( videoDetailsRequest
   ...
   }, 'jsonp');
   jqxhrs.push(jqxhr);
...
$.when.apply(undefined, jqxhrs).always(function () { /* your intended callback */

または、次を使用できます.pipe

//Create initial deferred object
var jqxhr = $.Deferred();
   ...for loop...
   jqxhr = jqxhr.pipe($.get(...
jqxhr.always(function () { /* callback */
于 2013-01-06T00:34:02.240 に答える