2017-02-06 4 views
1

Сценарий выглядит следующим образом:Chain JQuery обещает, но обрабатывать отказы отдельно

  • вызов к серверу, который возвращает массив объектов, если все в порядке.
  • при возникновении ошибки на сервере, он возвращает сообщение json, содержащее сообщение об ошибке.

Из этого сценария, я хочу создать функцию, которая возвращает обещание, которое я могу использовать, как это от клиента:

initData() 
    .done(function(myArray) { 
     processData(myArray); 
    }) 
    .fail(function(response) { 
     console.log("An error occured: " + response.errorMessage); 
    }); 

Клиент не должен заботиться, что initData() делает вызов на сервер, он должен получить fail(), вызываемый как для сбоев ajax, так и для ошибок сервера.

Для этого мне нужны две вещи:

  1. Скрыть Провал вызова сервера и создать новый объект сообщения об ошибке.
  2. Сделать обещание неудачным, если вызов сервера возвращен с объектом сообщения об ошибке.

Вот что у меня есть:

function initData() { 
    var promise = $.getJSON(url); 

    return promise.then(function(response) { 
     if (typeof response !== 'undefined' && response !== null && typeof response.errorMessage !== 'undefined') { 
      // Do something to trigger fail() in the client caller. 
     } 
     return response; 
    }, function(resp) { 
     // This satisfies point 1 above. 
     return { errorMessage: "Server error." }; 
    }); 
} 

Как я могу удовлетворить второе требование? Я использую jquery 3.1.1.

Спасибо.

ответ

1

Просто выбросьте ошибку с вашего обратного вызова then. Вызывающий абонент «поймает» его в своем отказоустойчивом обратном вызове (хотя я предлагаю вам научиться использовать стандартные then и catch и прекратить использование jQuery-специфических done и fail).

function initData() { 
    var promise = $.getJSON(url); 

    return promise.then(function(response) { 
     if (typeof response !== 'undefined' && response !== null && typeof response.errorMessage !== 'undefined') { 
      throw new Error("uh oh!"); 
     } 
     return response; 
    }, function(resp) { 
     // This satisfies point 1 above. 
     throw new Error("server error"); 
    }); 
} 
+0

Спасибо. Не могли бы вы немного подробнее остановиться на рекомендуемой альтернативе? – Paul

+1

Просто прекратите использовать 'done' и' fail' - они специфичны для jQuery и до того, как jQuery обновит их реализацию, чтобы соответствовать спецификации Promise. Вместо этого вызывается 'then' и' catch', которые являются spec-compliant функциями. Они в основном работают одинаково, поэтому вы можете изменить свой «код клиента» на «.done (...). Fail (...)' to '.then (...). Catch (...)' и он работал бы (а также работал со стандартным обещанием). – Brandon

+0

Я настаивал, потому что я нашел решение, прежде чем публиковать вопрос, используя отложенные объекты, но у меня уже был записан вопрос, и мне было любопытно об альтернативах. Я уже пробовал использовать бросок после предложения друга, но к моему отчаянию это не сработало, потому что я использовал jquery 1.11.3 в начале, что не поддерживает это. Что касается вашего ответа, строка 'return {errorMessage:« Ошибка сервера ». }; 'не работает должным образом при использовании then/catch. Я считаю, что 'throw' является обязательным в этом случае. – Paul

1

Чтобы провалить обещание, просто throw результатом вместо return ИНГ его:

function initData() { 
    return $.getJSON(url)e.then(function(response) { 
     if (typeof response !== 'undefined' && response !== null && typeof response.errorMessage !== 'undefined') { 
      throw { errorMessage: "Response error." }; 
     } 
     return response; 
    }, function(resp) { 
     throw { errorMessage: "Server error." }; 
    }); 
} 

(Это работает только в JQuery 3. Для более ранних версий см Throwing an Error in jQuery's Deferred object)

Смежные вопросы