使用promise装饰器包装$ http调用

时间:2015-08-15 07:42:16

标签: angularjs decorator q

我有一个角色服务,我用它来跟我的后端沟通:

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

然而,这只会导致大量错误并且很多都会返回undefined。我想我应该在调用它时传递一个函数,但是我完全迷失了如何使这个工作

1 个答案:

答案 0 :(得分:5)

你让自己的生活过于复杂。只需使用promise chaining:

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