Angular $ q catch块可以解析promis吗?

时间:2016-03-04 15:43:24

标签: angularjs angular-promise

在过去的观察日里,我阅读了很多处理承诺的最佳实践。大多数帖子的一个中心点是:

  

因此,如果您在代码中编写[deferred]字样   [...],你做错了什么。1

在试验错误处理期间,我看到了一个意想不到的行为。当我链接承诺并且它进入第一个catch块时,第二个承诺得到解决而不被拒绝。

问题

  • 这是其他libs /标准(例如q,es6)中的正常行为吗?捕获的错误计算为像try / catch一样解决?
  • 如何拒绝catch块中的promise,以便第二个获取,使用相同的错误/响应对象调用?

实施例

在此示例中,您会看到“我在这里,但这是一个错误”

Full Plunker

function BaseService($http, $q) {
  this.$http = $http;
  this.$q = $q;
}

BaseService.prototype.doRequest = function doRequest() {
  return this.$http({
      method: 'GET',
      url: 'not/exisint/url'
    })
    .then(function (response) {
      // do some basic stuff
    })
    .catch(function(response) {
      // do some baisc stuff e.g. hide spinner
    });
}


function ChildService($http, $q) {
  this.$http = $http;
  this.$q = $q;
}

ChildService.prototype = Object.create(BaseService.prototype);

ChildService.prototype.specialRequest = function specialRequest() {
  return this.doRequest()
    .then(function (response)  {
      alert('I am here but It was an error');
    })
    .catch(function (response) {
      // do some more specific stuff here and
      // provide e.g. error message
      alert('I am here but It was an error');
      return response;
    });
}

解决方法:

通过此解决方法,您可以解决此问题,但您必须创建新的延迟。

BaseService.prototype.doRequest = function doRequest() {
  var dfd = this.$q.defer();

  return this.$http({
      method: 'GET',
      url: 'not/exisint/url'
    })
    .then(function (response) {
      // do some basic stuff
      dfd.resolve(response);
    })
    .catch(function(response) {
      // do some basic stuff e.g. hide spinner
      dfd.reject(error);
    });
}

2 个答案:

答案 0 :(得分:2)

您的解决方法几乎是正确的,您可以将其简化为以下内容:

BaseService.prototype.doRequest = function doRequest() {  
  return this.$http({
      method: 'GET',
      url: 'not/exisint/url'
    })
    .then(function (response) {
      // do some basic stuff
      return response;
    }, function (error) {
      return this.$q.reject(error);
    });
}

$q.reject是创建延迟的快捷方式,可立即被拒绝。

  1. 是的,这也是其他库中的默认行为。 .then.catch只是将返回值包装到新的承诺中。您可以返回被拒绝的承诺,以使.catch链工作。
  2. 您也可以采取相反的做法,例如当您想要在成功回调中拒绝承诺时出于某种原因:

    function getData() {
       return this.$http.get(endpoint).then(result => {
          // when result is invalid for whatever reason
          if (result === invalid) {
             return this.$q.reject(result);
          }
    
          return result;
       }, err => this.$q.reject(err));
    }
    
    getData().then(result => {
       // skipped
    }, error => {
       // called 
    });
    
    1. 见上面的例子

答案 1 :(得分:0)

只需添加到Dieterg's答案和解决方法,您还可以将代码包装到$ q构造函数中:

BaseService.prototype.doRequest = function doRequest() {
   return $q(function (resolve, reject) {
      $http.get('not/exisint/url').then(function (response) { // success
          /* do stuff */
          resolve(response);
      }, function (error) { // failure
          /* do stuff */
          reject(error);
      });
   });
};