JQuery отложил превратить неудачу в успех - PullRequest
7 голосов
/ 07 июня 2011

Таким образом, при использовании jQuery deferreds и $.when для параллельной загрузки многих объектов.

$.when(
  a.ajax(), b.ajax(), c.ajax()
).then(
  //do something when all are complete
  complete();
);

Теперь, b.ajax() иногда завершается ошибкой, но на самом деле мне все равно.Я просто хочу подождать, пока все вызовы не будут завершены, прежде чем вызывать complete ().

К сожалению, как только b терпит неудачу, when() отклоняет и никогда не запускает обратный вызов then().Это ожидаемое поведение AFAIK для $.when(), однако в данном случае меня это устраивает.

Я фактически хочу получить способ сказать:

$.when(
  a.ajax(), b.ajax().fail(return success), c.ajax()
).then(...)

Или, возможно, есть другой способ использованияwhen(), или более подходящая конструкция?

Ответы [ 4 ]

6 голосов
/ 13 мая 2015

Если вы хотите зафиксировать невыполнение обещания и преобразовать его в успех, вы можете использовать failFilter со значением , а затем , чтобы вернуть разрешенное обещание, например, так:

deferredCall.then(function(answer) { 
   // this is success. you might transform the answer here.
   return transformed;
}, function() {
   // this is a fail. you might resolve the fail with an empty object.
   return $.Deferred().resolve({}).promise();
});

Это обеспечит возможность продолжения цепи после неисправности.

Итак, для вашего примера, вы можете сделать это:

$.when([
   a.ajax(),
   b.ajax().then(function(answer) { 
       return answer; 
   }, function() {
       return $.Deferred().resolve({}).promise();
   }),
   c.ajax()
]).then(function(results) {
    // etc.
});

Пример 2. В моих приложениях я иногда использую , а затем , чтобы получить реляционные данные для конкретной сущности и учесть возможность 404 указать, что таких отношений не существует:

getEntity(id).then(function(entity) {
    return getAssociation(id).then(function(association) {
        entity.association = association;
        return entity;
    }, function() {
        entity.association = null;
        return $.Deferred().resolve(entity).promise();
    });
}).done(function(entity) {
    // etc.
});

Обратите внимание, в старых ответах предлагается использовать метод pipe . Начиная с версии jQuery 1.8 этот метод устарел.

3 голосов
/ 25 октября 2011

Здесь есть что-то лучше, чем взломать неудачу и добиться успеха.

Малоизвестный факт, $ .when () немедленно выполнит обратный вызов then (), если какой-либо из параметров потерпит неудачу.Это по замыслу.Чтобы процитировать документацию:

http://api.jquery.com/jQuery.when/

В случае множественных отсрочек, когда один из отложенных отклонен, jQuery.when немедленно запускает failCallbacks для своего главного отложенного элемента.Обратите внимание, что некоторые из отложенных могут все еще быть неразрешенными в этой точке.Если вам необходимо выполнить дополнительную обработку для этого случая, например отменить незаконченные запросы Ajax, вы можете хранить ссылки на базовые объекты jqXHR в замыкании и проверять / отменять их в failCallback.

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

Итак, я построил для вас $ .whenAll () :) Он всегда ждет, пока все они решаттак или иначе:

http://jsfiddle.net/InfinitiesLoop/yQsYK/

1 голос
/ 28 июня 2011

Итак, я понял это в конце, посмотрите мой ответ кому-то еще с такой же проблемой:

как обмануть jqXHR, чтобы всегда добиться успеха

ответ одинокого днябыло опрятно, но не совсем то, что я хотел.

1 голос
/ 07 июня 2011

Вы можете довольно легко построить $.onFailSucceed, обернув объект $.Deferred:

$.onCompleteSucceed = function(oldDfd) {
    var newDfd = $.Deferred();

    oldDfd.always(newDfd.resolve);

    return newDfd.promise();
}

Затем можно обернуть соответствующие вызовы в этом методе:

$.when(
  a.ajax(), $.onCompleteSucceed(b.ajax()), c.ajax()
).then(...)
...