jQuery Deferred — добавление обратного вызова в отложенный контракт

Я пытаюсь добавить еще один асинхронный вызов в контракт существующего Deferred до того, как его состояние будет установлено на успех. Вместо того, чтобы пытаться объяснить это на английском языке, посмотрите на следующий псевдокод:

$.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!'); });

По сути, вызов 2 зависит от результатов вызова 1. Я хочу, чтобы вызов 1 и вызов 3 выполнялись параллельно. После завершения всех трех вызовов я хочу, чтобы код All Done выполнялся. Насколько я понимаю, Deferred.pipe() должен связать другой асинхронный вызов с данным отложенным, но на практике я всегда завершаю вызов 2 после завершения All Done.

Кто-нибудь знает, как заставить jQuery Deferred делать то, что я хочу? Будем надеяться, что решение не требует дальнейшего разделения кода на куски.

Спасибо за любую помощь.

ОБНОВЛЕНИЕ: см. мой дополнительный вопрос .


person MgSam    schedule 28.09.2012    source источник


Ответы (1)


Вы должны вызвать .pipe для отложенного объекта, возвращенного первым вызовом $.ajax, а не внутри его обратного вызова успеха (это вообще не имеет никакого эффекта):

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

.pipe возвращает новый отложенный объект, который разрешается только после разрешения исходного отложенного объекта и возвращенного.

person Felix Kling    schedule 28.09.2012
comment
это происходит в 1.8+, где .then теперь эквивалентно самому .pipe - person Alnitak; 28.09.2012
comment
Ах да, я что-то такое припоминаю... они действительно должны обновить документы. Я думаю, что в этом случае это не имеет большого значения, но имеет больше смысла. Спасибо! - person Felix Kling; 28.09.2012
comment
ISTR разница в том, что .pipe возвращает новое обещание, тогда как .then возвращает исходное обещание. - person Alnitak; 28.09.2012
comment
Хорошо, это работает. Есть ли способ передать результаты вызова 1 в функцию вызова 2 без использования замыканий или глобальных переменных? - person MgSam; 28.09.2012
comment
@MgSam: Конечно, результат передается в качестве аргументов обратного вызова .pipe. Я не уверен, какие значения передаются для ответов Ajax, поэтому просто запишите аргументы и посмотрите, что вам нужно. - person Felix Kling; 28.09.2012
comment
В порядке. Моя ситуация на самом деле сложнее, чем показало мое первоначальное объяснение. Пожалуйста, смотрите обновленный вопрос. - person MgSam; 28.09.2012