【问题标题】:Wrapping $http call with promise decorator用 promise 装饰器包装 $http 调用
【发布时间】:2015-08-15 07:42:16
【问题描述】:

我有一个 Angular 服务,用于与我的后端进行通信,如下所示:

getMyBooks: function(userId) {
  var deferred = $q.defer();
  $http.get('/api/users/' + userId + '/books')
    .success(function(data) {
      deferred.resolve(data);
    }).error(function(data) {
      deferred.reject(data);
    });
  return deferred.promise;
},

但是,在使用了 6 个左右的这些函数之后,代码开始变得笨拙。

所以我尝试使用装饰器模式重构它,从这里松散地复制加倍装饰器:http://javascript.info/tutorial/decorators

给我这个更新的代码:

var bookService = function ($http, $q, $filter) {

  var deferredwrapper = function(f) {
      return function() {
        var deferred = $q.defer();
        f.apply(this, arguments)
          .success(function(data) {
            deferred.resolve(data);
          }).error(function(data) {
            deferred.reject(data);
          });
        return deferred.promise;
      }
  };

  var funcs = {
    getBooks: deferredwrapper(
       function(userId) { $http.get('/api/users/' + userId + '/books') }
    )
  };

  return {
    getMyBooks: function() { funcs.getBooks }
  }
};

但是,这只会导致大量错误并返回大量未定义。我想当我应该调用它或其他东西时我正在传递一个函数,但我完全不知道如何使它工作

【问题讨论】:

  • 这是一种反模式。所有常见的做法称为 promise wrapping,应该避免,因为它没有任何用途,并且会使您的代码更难理解。请参阅 JB Nizet 的答案以获得更好的解释。

标签: angularjs decorator q


【解决方案1】:

你把自己的生活弄得太复杂了。只需使用承诺链:

getMyBooks: function(userId) {
  return $http.get('/api/users/' + userId + '/books').then(function(response) {
    return response.data;
  }).catch(function(response) {
    return $q.reject(response.data);
  });
}

也就是说,您的技术不起作用,因为您作为参数传递给 deferredwrapper() 的函数没有返回任何内容。包装器期望该函数返回一个 HTTP 承诺。改变

function(userId) { $http.get('/api/users/' + userId + '/books') }

function(userId) { return $http.get('/api/users/' + userId + '/books'); }

您在返回服务时犯了同样的错误:您分配的函数既不执行也不返回任何内容给getMyBooks。改成

getMyBooks: funcs.getBooks

【讨论】:

    猜你喜欢
    • 2017-09-13
    • 2021-08-16
    • 2015-02-22
    • 2023-04-03
    • 1970-01-01
    • 2018-11-28
    • 2021-05-20
    • 2015-04-27
    • 2018-03-07
    相关资源
    最近更新 更多