jQuery .always()似乎在$ .get()请求实际完成之前触发

时间:2013-01-06 00:16:24

标签: ajax jquery asynchronous jquery-callback

这可能是我对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()回调的目的是解释这一点。非常感谢任何帮助我理解的东西。谢谢!

1 个答案:

答案 0 :(得分:6)

您设置此方法的方式,.always回调将在循环中的最后 ajax请求完成后立即触发。这可能与其他人无关。当循环中的所有请求都已完成或外部请求已完成时,我无法确定是否要触发它。

对于外部请求,这很容易。只需将来电链接到.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 */