Обработка отложенных АСИНХРОННЫХ вызовов AJAX

#javascript #jquery #ajax #jquery-deferred

#javascript #jquery #ajax #jquery-отложенный

Вопрос:

У меня есть функция, которая выглядит примерно так:

 function refreshData() {
    service.getSettings().done(function (settings) {
        // DATA 1
        service.getData1(settings).done(function (result) {
            // do something local with result
            // partial resolve 1
        });
        // DATA 2
        var localData = service.getLocalData();
        if (localData.length) {
            service.getData2(settings, localData).done(function (result) {
                // do something local with result
                // partial resolve 2
            });
        } else {
            $('#list').empty();
            // or partial resolve 2
        }
    });
}
  

Что я хочу сделать, так это создать отложенный объект для этой функции, чтобы я знал, когда обновление данных будет полностью завершено. Я знаю, что мог бы связать их вместе с $.when , но я хочу, чтобы два вызова AJAX выполнялись независимо, и мне все равно, завершится ли один раньше другого.

Я отметил выше, где я хочу разрешить каждую часть. Я просто не уверен, как это сделать.

Моей конечной целью был бы вызов, подобный этому:

 refreshData().done(function() {    
    // hide loader
});
  

Ответ №1:

Основные вещи, которые вам нужно сделать, это :

  • чтобы вернуть составное обещание, сгенерированное $.when(partial1, partial2)
  • чтобы сгенерировать (и вернуть) это обещание внутри .then() , привязанное к вашему внешнему service.getSettings()

Вы также можете захотеть сделать сбой наблюдаемых частей, по крайней мере, для отладки.

 function refreshData() {
    return service.getSettings().then(function (settings) {//note `return` and `.then()`
        var partial1, partial2; // declare two promises

        // utility function make error observable - avoids repetition below
        function handleError(err) {
            console.error(err);
        });

        partial1 = service.getData1(settings).done(function (result) {
            //do something local with result
        }).fail(handleError);//make failure of partial1 observable

        var localData = service.getLocalData();//assume this is synchronous
        if (localData.length) {
            partial2 = service.getData2(settings, localData).done(function (result) {
                //do something local with result
            }).fail(handleError);//make failure of partial2 observable
        } else {
            partial2 = $('#list').empty().promise();//sneaky way to generate a resolved promise
        }

        return $.when(partial1, partial2);//as we are inside a `.then()`, the promise generated here is effectively returned by refreshData().
    });
}
  

смотрите комментарии в коде

Вызовите следующим образом :

 refreshData().done(function() {    
    // hide loader
}).fail(function(err) {
    // indicate failure
});
  

Комментарии:

1. 1 за использование уже доступных обещаний вместо создания новых отложенных.

Ответ №2:

как насчет чего-то подобного,

 function refreshData() {
    var def1 = $.Deferred();
    var def2 = $.Deferred();

    service.getSettings().done(function (settings) {
        service.getData1(settings).done(function (result) {
            def1.resolve(result);
        });
        var localData = service.getLocalData();
        if (localData.length) {
            service.getData2(settings, localData).done(function (result) {
                def2.resolve(result);
            });
        } else {
            $('#list').empty();
            def2.resolve();
        }
    });    

    // return aggregated promise
    return $.when(def1, def2);
}


refreshData().done(function(r1, r2) {    
     // hide loader
});
  

Примечание: непроверенный

Комментарии:

1. Вам нужны отдельные отсрочки для def1 и def2 . Не могу использовать тот же, что у вас здесь. Вероятно, можно было бы также использовать существующие обещания, а не создавать новые.

2. @jfriend00 спасибо, приятель, я знал, что найдется решение получше этого, но в то время оно меня не поразило. Roamer-1888 на самом деле элегантен. Отредактировал ans, чтобы указать отдельные отсрочки.