Получить ответ нескольких отложенных объектов в jquery

Ниже приведены мои множественные вызовы ajax с обещаниями.

$(window).load(function(){
 $.when(getApiModemList()).done(function(vendors){

    var deferreds = calculateApiBalances(vendors);

    $.when.apply($,deferreds).done(function(balance) {
     console.log(balance);
     console.log("All Done");
    });

});


function getApiModemList(){
   return $.getJSON("url");
}

 function calculateApiBalances(vendors)
  {
   var defer=[];
   $.each(vendors,function(k,v){
    defer.push($.getJSON(someurl));
   });
  return defer;
 }

 });

Функция calculateApiBalances() возвращает мне некоторый баланс, который мне нужно суммировать, чтобы получить общий баланс. Но при печати console.log(баланс) он не предоставляет мне действительный массив баланса json. Другая проблема заключается в том, что если какой-либо из моих ajax-вызовов в calculateApiBalances() терпит неудачу, он не печатает All Done. Что нужно сделать в приведенном выше коде, чтобы добиться этого.


person Vibhas    schedule 23.04.2015    source источник
comment
Прежде всего, избегайте отложенного антишаблона!   -  person Bergi    schedule 23.04.2015
comment
Что должен содержать массив в случае ошибки? Обычно объединенное обещание просто отклоняется.   -  person Bergi    schedule 23.04.2015
comment
@Берги. Исправлена ​​​​проблема с шаблоном. Меня не волнует, если какой-то вызов ajax не работает, мне нужно только учитывать баланс успешных вызовов ajax. Возможно ли это?   -  person Vibhas    schedule 23.04.2015


Ответы (1)


Но при печати console.log(баланс) он не предоставляет мне действительный массив баланса json.

Это странная вещь $.when. Он не предоставляет вам массив, но вызывает ваш обратный вызов с несколькими аргументами.

Другая проблема заключается в том, что если какой-либо из моих ajax-вызовов в calculateApiBalances() терпит неудачу, он не печатает All Done.

Да, потому что, когда одно обещание терпит неудачу, все обещание $.when() немедленно отклоняется, и у вас нет никакого обработчика ошибок. Вам придется отлавливать ошибки по отдельности, если вы хотите всегда получать массив (возможно, неверных ответов). См. также $.Deferred: как определить, когда каждое обещание выполнено.

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

Прежде всего, избегайте отложенного антишаблона :-)

$(window).load(function() {
    getApiModemList().then(calculateApiBalances).then(function() {
        var balance = Array.prototype.slice.call(arguments);
        console.log(balance);
        console.log("All Done");
    });
});


function getApiModemList() {
    return $.getJSON(somurl).then(function(res) {
        return res.data;
    });
}

function calculateApiBalances(vendors) {
    return $.when.apply($, $.map(vendors, function(v, k) {
        return $.getJSON(someurl).then(null, $.when);
    }));
}

EDIT by Roamer:

А вот вариант основной процедуры с механизмом суммирования балансов.

    getApiModemList().then(calculateApiBalances).then(function() {
        var sumOfBalances = Array.prototype.reduce.call(arguments, function(tot, obj) {
            return tot + (+obj.balance || 0);
        }, 0);
        console.log(sumOfBalances);
        console.log("All Done");
    });

obj — это объект, обещанный $.getJSON(someurl) в calculateApiBalances(). В случае ошибки $.getJSON() obj будет объектом jqXHR, obj.balance будет undefined и +obj.balance будет NaN, поэтому по умолчанию добавляется ноль; в противном случае добавьте obj.balance .

Если вы хотите узнать, сколько запросов getJSON были успешными, а сколько нет, вам нужно написать еще немного кода, но не так много.

person Bergi    schedule 23.04.2015
comment
@Roamer: Ах, я пропустил это требование, спасибо за его редактирование. Однако ваше редактирование находится на грани законности, как я могу проголосовать за него? :-) - person Bergi; 23.04.2015
comment
Берги, на грани законности? - person Roamer-1888; 23.04.2015
comment
Извините за странный термин, здесь не носитель языка. Я имел в виду, что редактирование было пограничным и, вероятно, не было бы принято как предложение по редактированию (слишком радикальное изменение, попытка ответить). Хотя я в порядке, спасибо. - person Bergi; 23.04.2015
comment
Берги, что интересно, если вы вышли из SO (или получили RSS-канал в почтовом клиенте), ссылка на редактирование гласит: «Улучшите этот ответ», который, по-видимому, приглашает к редактированию такого рода. Кстати, я всегда предполагал, что английский был вашим родным языком :-) - person Roamer-1888; 23.04.2015
comment
О, спасибо. Да, я не против таких правок, и сам иногда их делаю, но я просто не видел их повсеместно - person Bergi; 23.04.2015