2016-09-13 4 views
0

В каждой $ HTTP вызова с .then(successFunc) и .catch(errFunc) (в качестве альтернативы then(successFunc, errFunc)then/success всегда вызывается (обещание успешно решена).

Пример

$http.get('/some/resource') 
// /some/resource --> HTTP 400 
    .then(function(response) 
    { 
     console.log('success'); 
    }) 
    .catch(function(reason) 
    { 
     console.log('error'); 
    }) 

// Console: 
// - success 

Это предполагаемое поведение или причину этого?

+0

Это не поведение по умолчанию, но может быть связано с ответом-перехватчиком, который вы использовали в своем приложении. Обычно ответные перехватчики являются глобальными, и вы можете не знать о его присутствии, если это большое приложение. Не могли бы вы изолировать этот код в скрипте, чтобы воспроизвести ту же проблему? – arunkjn

+0

Я создал это как ответ на вопрос Q & A, чтобы сохранить его для других людей, поскольку здесь не было похожего вопроса о SO. Вы точно описываете вопрос, который я хотел бы указать на этот пост (также см. Мой подробный ответ). Еще спасибо за ответ :) – Aides

ответ

1

Нет, это не намеренное поведение. Обычно оно должно звонить .then() на HTTP 2xx и .catch() по телефону HTTP 4xx и HTTP 5xx (не уверены в других).

Описанное поведение, вероятно, вызвано еще одним .catch(), возвращением разрешенного обещания.

В слегка измененном примере:

//In some Service: 
function getResources() 
{ 
    $http.get('/some/resource') 
    // /some/resource --> HTTP 400 
     .then(function(response) 
     { 
      console.log('service success'); 
      return response; 
     }) 
     .catch(function(reason) 
     { 
      console.log('service error'); 
      // IMPORTANT: although this is returned 
      // in a .catch() it returns a resolved promise 
      return reason; 
     }); 
} 

//In some Controller: 
someService.getResources() 
    .then(function(response) 
    { 
     console.log('controller success'); 
    }) 
    .catch(function(reason) 
    { 
     console.log('controller error'); 
    }); 


// Console: 
// - service error 
// - controller success 

Обратите внимание, что это также может быть вызвано зарегистрированной http interceptor:

$httpProvider.interceptors.push(function($q) 
{ 
    return { 
     'response': function(response) 
     { 
      // do something 
      return response; 
     }, 
     'responseError': function(rejection) 
     { 
      // do something 
      return rejection; // <-- this causes the problem 
      // instead do 
      return $q.reject(rejection); 
     } 
    } 
} 
1

Вашего пример преобразует отказа в разрешенном обещание.

$http.get('/some/resource') 
// /some/resource --> HTTP 400 
    .then(function(response) 
    { 
     console.log('success'); 
     //IMPORTANT -- return to chain data 
     return response; 
    }) 
    .catch(function(reason) 
    { 
     console.log('error'); 
     //IMPORTANT -- throw to chain rejections 
     throw reason; 
    }) 

Когда обработчик задвижки пропускает throw заявления, функция возвращает undefined, который преобразует отказ в обещание, устраняющее undefined.

Посмотрите в своем коде на http interceptor, который следует за тем же самым ошибочным рисунком.

Правило в функциональном программировании всегда return (или throw).

+0

Это первый раз, когда я видел ключевое слово 'throw', используемое с обещаниями. Есть ли у вас пример демонстрации правильного поведения? – Aides

+0

См. [Угловой порядок выполнения с '$ q'] (http://stackoverflow.com/a/34326388/5535245) – georgeawg

+0

Я только что протестировал его в скрипке - работает, как описано, однако он по-прежнему распространяет ошибку в браузере, поэтому я предпочел бы «возвращать $ q.reject (reason)' over' throw reason' (см. [Angular $ http docs] (https://docs.angularjs.org/api/ng/service/$http#interceptors)). – Aides

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