AngularJS$http承诺异常不会冒泡

AngularJS $http promise exception not bubbling up

本文关键字:异常 http 承诺 AngularJS      更新时间:2023-09-26

我遇到了一个问题,即$http承诺没有从执行它的服务冒泡到调用服务方法的任何地方。

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

// 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

似乎服务返回的承诺只是一个简单的承诺,它接受.then(),但不区分successfail,如文档中解释的那样:

返回一个承诺,当请求成功或失败时,该承诺将解析为响应对象。

所以。。。我错过了什么吗?以前有人遇到过这样的问题吗?

谢谢!

我相信你和我了解承诺时有类似的感觉。 这是我提出的一个与你相似的问题的答案。我只是惊讶于错误没有传播。使用克里斯·科瓦尔的Q。如果链式承诺的整个生命周期中抛出任何错误,我应该如何捕捉?

引用这个答案:

处理的拒绝就像捕获的异常。它停止传播 既然很好,它就被处理了。如果您想处理拒绝和 保持拒绝,你需要重新抛出,再次,就像在同步中一样 法典。

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. 您可以决定不在服务中记录错误,而是直接在控制器中处理它。

个人会选择1,但那是因为当承诺没有记录他们的错误时,我无法忍受,在没有日志记录的情况下很难追踪什么。

auth.service.js 错误处理程序必须返回被拒绝的承诺:

return $q.reject(response);

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

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

在授权方法中创建一个承诺并返回它。

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);