jQuery Deferred - Adding a callback to the Deferre

2019-07-09 13:54发布

问题:

I'm trying to add another asynchronous call to the contract of an existing Deferred before its state is set to success. Rather than try and explain this in English, see the following pseudo-code:

$.when(
    $.ajax({        
        url: someUrl,
        data: data,
        async: true,        
        success: function (data, textStatus, jqXhr) {
            console.log('Call 1 done.')
            jqXhr.pipe(
                $.ajax({        
                    url: someUrl,
                    data: data,
                    async: true,        
                    success: function (data, textStatus, jqXhr) {
                        console.log('Call 2 done.');
                    },       
                })
            );
        },       
    }),
    $.ajax({        
        url: someUrl,
        data: data,
        async: true,        
        success: function (data, textStatus, jqXhr) {
            console.log('Call 3 done.');
        },       
    })
).then(function(){ console.log('All done!'); });

Basically, Call 2 is dependent on the results of Call 1. I want Call 1 and Call 3 to be executed in parallel. Once all 3 calls are complete, I want the All Done code to execute. My understanding is that Deferred.pipe() is supposed to chain another asynchronous call to the given deferred, but in practice, I always get Call 2 completing after All Done.

Does anyone know how to get jQuery's Deferred to do what I want? Hopefully the solution doesn't involve ripping the code apart into chunks any further.

Thanks for any help.

UPDATE: Please see my follow up question.

回答1:

You have to call .pipe on the deferred object returned by the first $.ajax call, not inside its success callback (this does not have any effect at all):

$.when(
    $.ajax({        
        // ...      
    }).pipe(function() {
        // return a deferred object from .pipe
        return $.ajax({        
            // ...      
        });
    }),
    $.ajax({        
        // ...       
    })
).done(function(){ console.log('All done!'); });

.pipe returns a new deferred object which only gets resolved once both, the original deferred object and the returned one get resolved.