Выполнение затем после улова

У меня есть следующая скрипка: http://jsfiddle.net/thelgevold/3uv9nnjm/6/

angular.module('hello',[]).controller('helloController',function($q){

    console.clear();
    function someService(){
       var deferred = $q.defer();
       deferred.reject({e:'error'}); 
       return deferred.promise;
    } 

    function callService(){
        return someService().then(function(obj){
           console.log('first then');
        }).
        catch(function(e){
            console.log('error1');
            var deferred = $q.defer();
            deferred.reject({e:'error'}); 
            return deferred.promise;
        });
    }

    callService().catch(function(e){
      console.log('error2');
    }).then(function(e){
      console.log('second then');
    });

});

Это, по сути, просто быстрый $q обещающий POC. Мой вопрос: почему последнее предложение вызывается, когда обещание отвергается? Выход выглядит следующим образом:

Error1

Error2

секунд, затем

Я понимаю, почему печатается error1/error2, но я думал, что вторая строка не должна печататься, поскольку обещание было отклонено. Я думал, что он будет опускать "второй тогда" по той же причине, что и "первым тогда". Любые мысли?

Ответ 1

Прежде чем начать, не делайте этого:

var deferred = $q.defer();
deferred.reject({e:'error'}); 
return deferred.promise;

Сделайте это:

return $q.reject({e:'error'});

Или предпочтительно это:

return $q.reject(new Error('error'));

Остерегайтесь отложенного антипаттера.

Теперь, для ответа на ваш вопрос.


.catch() после вашего вызова callService() обнаруживает ошибку и не создает новую ошибку. Он по существу "обработал" ошибку, и следующий обработчик .then() может быть вызван.

Синхронный эквивалент кода вашего примера:

function someService() {
  throw { e: 'error' };
}

function callService() {
  try {
    var obj = someService();
    console.log('first then');
  } catch (e) {
    console.log('error1');
    throw { e: 'error' };
  }
}

var e;
try {
  e = callService();
} catch (e) {
  console.log('error2');
}

console.log('second then');