在我自己的Angular服务中,如何将返回值返回给调用该服务的Controller?

时间:2014-04-27 21:50:45

标签: javascript angularjs http service promise

我在找出$ http中的成功和错误回调时遇到了麻烦,而#34;那么"承诺的一部分。 $ http服务返回一个promise。是"成功"回调一个例子"然后"? 如果我在自己的服务中粘贴$ http怎么办?我该怎么做?

我认为代码更容易显示我的问题:

app.controller('MainCtrl', function ($scope, $log, BooksService) {
    BooksService.retrieveAllBooks().then(function(results) {
      $scope.allBooks = results;
    });
  });


app.factory('BooksService', function($http,$log) {
  var service = {
    retrieveAllBooks: function() {
      return $http({
        method: 'GET','https://hugebookstore.org/allbooks'
        headers: {
            "Content-Type": "application/json",
            "Accept": "application/json"
        }
      }).success(function(data, status, headers, config) {
         var allbooks = transformDataIntoBooksArray(data);//this function exists and just takes raw data and turns them into Book objects
         return allbooks;/*how is this "success" callback related to the "then"() callback in app.controller above?*/
      };
      }).error(function(data, status, headers, config) {
        $log.error('here is an error'+data + status + headers + config);
      });
    }
  };
  return service;
});

有关app.controller代码的问题:

我是否需要在"then()"

中使用app.controller?功能

我只是希望我的控制器使用BooksService来获取所有图书的列表。 BooksService已经有一个" then"条款的类型,即" success"打回来。好像我有一个不必要的" then"。真的吗?

此外,何时是" then"我可以在then's回调函数的参数中添加任何内容吗?

我不明白默认情况下提供的参数以及我可以添加的内容。

有关app.factory代码的问题:

首先,这就是我理解要执行的代码。

我使用factory()方法而不是Angular中提供的service()方法创建BooksService。 我定义了一个名为retrieveAllBooks()的函数,它在Angular中使用$ http进行异步GET请求,它本身就是一个服务。 RetrieveAllBooks()只不过是$ http GET服务的包装器,它使客户端可以轻松地调用BooksService.retrieveAllBooks()并传递一组Book对象。

" success"回调已执行,它与" then"的关系是什么?我的app.controller?

中的回调

我的return()回调中的success值永远不会返回app.controller。为什么?

如何将allbooks数组返回到最初称为BooksService.retrieveAllBooks()的app.controller?

success回调中是否还允许其他参数?

我需要从retrieveAllBooks()函数定义返回什么?我是否单独返回$http promise,还是需要return来自成功和error回调的内容?

我知道这是漫长的,但我希望有人可以帮助我,b / c这样做模式 - 将我的网络电话分离到自己的service图层而不是直接调用$ http在我的controller图层内,将一遍又一遍地完成。

谢谢!

1 个答案:

答案 0 :(得分:2)

successerror处理程序特定于$http返回的承诺。但是,它们与.then(function onFulfill(){}, function onReject(){})类似。

如果您想直接返回该承诺或实施其他内容,则取决于您。

通常,您的控制器不应该关心您的服务如何处理请求。因此,在我看来,你不应该直接回报这个承诺。只需处理您服务中的成功和错误案例。如果请求成功则返回结果,如果请求失败则抛出错误。

然后,您可以在控制器中使用通用.then(function onFulfill(){}, function onReject(){})模式,因为它始终有效,并且在Angular中具有承诺。

onFulfill回调始终将结果作为参数接收,onReject回调会将错误作为参数接收。

那么,你有什么选择?您可以完全删除服务中的.success.error回调,并在控制器中处理成功案例中的转换,或创建新的延迟承诺以返回转换后的结果:

app.factory('BooksService', function($http,$log,$q) {
  var service = {
    retrieveAllBooks: function() {
      var deferred = $q.defer();
      $http({
        method: 'GET','https://hugebookstore.org/allbooks'
        headers: {
            "Content-Type": "application/json",
            "Accept": "application/json"
        }
      }).success(function(data, status, headers, config) {
         var allbooks = transformDataIntoBooksArray(data);//this function exists and just takes raw data and turns them into Book objects
         deferred.resolve( allbooks );
      };
      }).error(function(data, status, headers, config) {
        $log.error('here is an error'+data + status + headers + config);
        deferred.reject( new Error( 'here is an error'+data + status + headers + config );
      });
      return deferred.promise;
    }
  };
  return service;
});

虽然我们可以保存,如果我们考虑:   - Angular已经跟踪错误   - 延期是超额的,可以避免   - 无论如何,Angular和serer都会生成Content-Type和Accept。   - 我们可以为我们的行动保存匿名包装

所以,我们最终得到:

app.factory('BooksService', function($http) {
  return {
    retrieveAllBooks: function() { 
      return $http.get('https://hugebookstore.org/allbooks').
             then(transformDataIntoBooksArray); // Error tracked by Angular already
      }
    }
});