AngularJS $ http承诺异常没有冒泡

时间:2016-03-10 10:21:20

标签: javascript angularjs

我遇到的问题是$http承诺没有从正在执行服务的服务中冒泡到任何调用服务方法的地方。

我在服务中有一个.authozire()方法,它返回$http Promise,如下所示:

// auth.service.js

function authorize(authParams) {
  var request = {
    method: 'POST',
    url: _apiUrl + 'oauth/token',
    data: authParams
  };

  return $http(request)
    .then(
      function successHandler(response) {
        // Correctly executed when success
        $log.debug('authService :: authorize => success', response);
      },
      function errorHandler(response) {
        // Correctly executed when error
        $log.debug('authService :: authorize => error', response);
      }
    );
}

上面的successerror方法(请注意,我已经不使用.success().error()方法,因为它们已被弃用)工作得很好在每种情况下,但是当我从控制器调用此方法时,它并没有按预期工作,如下所示:

// signin.controller.js

function submit() {
  authService.authorize(vm.formData)
    .then(
      function successHandler(response) {
        // Always executed even when there's an error
        $log.debug('SignInController :: submit :: authService.authorize() => success', response);
      },
      function errorHandler(response) {
        // NEVER executed
        $log.debug('SignInController :: submit :: authService.authorize() => error', response);
      }
    );
}

第一种方法successHandler总是被调用,即使出现错误且服务执行了自己的errorHandler

似乎Promise是由服务返回的,它只是一个接受.then()的简单承诺,但并没有区别successfail。在文档中:

  

返回Promise,当请求成功或失败时,将{{3}}解析为响应对象。

所以......我错过了什么吗?有没有人之前有这样的问题?

谢谢!

3 个答案:

答案 0 :(得分:3)

auth.service.js中,errorHandler必须返回被拒绝的承诺:

return $q.reject(response);

答案 1 :(得分:3)

我相信当我了解承诺时,你会有类似的感受。以下是我提出的与您类似的问题的答案。我很惊讶错误不是传播。 Using Kris Kowal's Q. How should I catch if any errors have been thrown throughout the life of a chained promise?

引用这个答案:

  

处理的拒绝就像一个被捕获的例外。它停止传播   好吧,它被处理了。如果你想处理拒绝和   保持拒绝你需要再次重新抛出,就像在同步中一样   代码。

try {
   throw new Error();
} catch(e){
    // handle error   
}
// no error here this code will keep running.
  

如果您希望它继续拒绝并处理它,您需要重新抛出:

try {
   throw new Error();
} catch(e){
    // handle error   
    throw e;
}
// this code will not run
  

与承诺相同,就像你写的一样。这不是特别的   奇怪的是承诺,这就是同步异常的工作原理。   如果你想传播 - 你重新投掷,否则 - 错误是   被视为处理。

  1. 因此,您可以继续在服务中记录错误,并通过在服务中添加return $q.reject(response);来为链中的下一部分收到相同的错误。您也可以在服务结束时说throw response;而不返回,它会将错误带到链的下一部分。
  2. 您可以决定不在服务中记录错误并直接在控制器中处理。
  3. 我个人认为1,但那是因为当承诺未记录错误时我无法忍受,如果没有记录,很难找到破坏的内容。

答案 2 :(得分:0)

问题是您已经在验证服务中处理承诺的回调。

要解决此问题,我们有两种可能的解决方案:

在authorize方法中创建一个promise并将其返回。

function authorize(params) {
   // create a promise object
   var dfd = $q.defer();

   var request = []; // request params here

   $http(request).then(
   function SuccessHandler(res) {
      def.resolve(res);
   }, 
   function ErrorHandler(res) {
      dfd.reject(res);
   });

   return dfd.promise();
}

另一种方法是发送http对象而不处理方法授权中的回调

return $http(request);