Javascript don';我不想在控制器中公开$http

Javascript don';我不想在控制器中公开$http,javascript,angularjs,Javascript,Angularjs,关于在服务中处理$http有很多问题,但我想稍微详细说明一下。我希望我的控制器能够使用类似于Angular$http API的API执行服务调用: $scope.login = function(user) { securityService.login(user).success(function(data) { $scope.data = data; }).error(function(data) { $scope.error = data; }); }; 这是

关于在服务中处理$http有很多问题,但我想稍微详细说明一下。我希望我的控制器能够使用类似于Angular$http API的API执行服务调用:

$scope.login = function(user) {
  securityService.login(user).success(function(data) {
    $scope.data = data;
  }).error(function(data) {
    $scope.error = data;
  });
};
这是一个很好的可读API。从表面上看,我在服务API中需要做的就是:

return {
  name : 'User Service',
  login : function(user) {
    return $http.post("/api/login", user);
  }
};
太好了,它会返回承诺和
成功
错误
消息。但是如果我想处理服务中的成功和失败案例,该怎么办?我想维护漂亮、可读的服务API。在本例中,可能我希望保留用户,以便可以公开类似于
securityService.currentUser()
或'securityService.isLoggedIn()'的方法


我尝试了
$http.post()。然后(…)
promise API,但它们返回整个http响应。同样,我想将HTTP与服务隔离开来,并维护一个类似的具体回调API。

您可以使用angular的
$q
登录
中做出自己的承诺:

var deferred = $q.defer(), 
    promise = deferred.promise;

$http.post("/api/login", user).success(...).error(...)

return promise;
在服务中的$http承诺成功/失败的情况下,解析/拒绝延迟对象

编辑:

扩展
$http.post

$http.post("/api/login", user).success(function(data) {
  if (data == "foo") { // success case?
    deferred.resolve('you logged in!');
  } else {
    deferred.reject('something really bad happened!');
  }
})

我刚刚运行了一个测试用例,如果我像这样从服务API返回承诺:

return $http.post("/api/login", user).success(...).error(...)
我也可以在控制器中执行相同的操作:

service.login(user).success(...).error(...)

两者都会被调用,服务第一,控制器第二。太好了

你能扩展你的例子吗?当然,对不起,应该在第一个例子中包括这一点。然后我在控制器中使用success和error并在每种情况下获取文本?是的,你可以通过这种方式隐藏http响应的复杂性。当然,承诺可以链接。如果您不想将控制器暴露于
$http
返回的内容的低级细节,而是想从API中返回更干净的内容,那么您应该做出自己的承诺。注意:不要忘记
.success().error()
语法不受
$q
支持,而是由
$http
模拟(您可以查看源代码promise是如何扩展的)。这意味着,如果您从Success/error的回调返回promise,则更改功能将无法工作。我建议使用
then(successCb,errorCb)
语法-然后您可以从回调返回其他承诺,并获得一个非常奇特的可链接工作流。