使用带角度的$ q服务

时间:2016-04-01 20:46:42

标签: angularjs angular-promise angularjs-http

如果你想创建一个只需要通过http调用一个API的服务,我仍然无法理解使用$ q服务的作用(它究竟会添加什么),在这种情况下我不会# 39;我知道为什么我不应该做以下事情(不使用$ q):

this.getMovie = function(movie) {
  return $http.get('/api/v1/movies/' + movie)
    .then(
    function(response) {
      return {
        title: response.data.title,
        cost: response.data.price
      });
    },
    function(httpError) {
      // translate the error
      throw httpError.status + " : " +
        httpError.data;
    });
};

4 个答案:

答案 0 :(得分:4)

非常好的问题,很少有人欣赏答案。

考虑一下:

this.getMovie = function(movie) {
  return $http.get('/api/v1/movies/' + movie);
};

很棒的代码但这些规则适用:

$ http将解决2xx响应,否则将拒绝。有时候我们不想要这个。我们想拒绝决议并决定拒绝。当您考虑HEAD请求来检查某些内容是否存在时,这是有道理的。

/book/fred返回200的HEAD请求显示存在fred book。但是如果我的函数测试的是fred是否是唯一的,那就不是了,所以我们想拒绝200.这就是$ q进来的地方。现在我可以这样做:

var defer = $q.defer();
$http.head('/book/fred').then(function(response) {
    // 2xx response so reject because its not unique
    defer.reject(response);
}).catch(function(failResponse) {
    defer.resolve(failResponse);
});
return defer.promise;

$ q让我可以完全控制何时拒绝和何时解决。

此外,$ q允许我拒绝或解决任何价值。因此,如果我只对一些响应感兴趣,我可以解决我感兴趣的一点。

最后,我可以使用$ q将基于非承诺的代码转换为承诺。

var a = 5;
var b = 10;
var defer = $q.defer();
var resolve(a+b);
return defer.promise;
波什,如果我需要一个承诺作为我的回报价值,那么我就有一个承诺。

在模拟单元测试时,这也很棒。

答案 1 :(得分:2)

$http$timeout$resource等AngularJS服务在内部使用$q服务来生成承诺。通过这些服务,通常无需注入$q服务。事实上,如果您看到$q.defer与这些服务一起使用,您应该问Is this a “Deferred Antipattern”?

$q服务的某些方法在某些情况下很有用。

$q.all方法用于等待多个承诺。

var promise1 = $http.get(url1);
var promise2 = $http.get(url2);

$q.all([promise1, promise2]).then( responseArray ) {
    $scope.data1 = responseArray[0].data;
    $scope.data2 = responseArray[1].data;
}).catch( function ( firstError ) {
    console.log(firstError.status)
});

.catch方法可用于将拒绝的承诺转换为履行的承诺。反之亦然.then方法。无需使用$q.defer。有关详细信息,请参阅Angular execution order with $q

$q.when方法对于从未知来源生成承诺非常有用。

 var promise = $q.when(ambiguousAPI(arg1));

$q.when方法在所有情况下都会创建$q承诺,ambiguousAPI是否返回值,$q承诺或来自其他库的承诺。

因为调用promise的.then方法会返回一个新的派生promise,所以很容易创建一个promise链。可以创建任何长度的链,并且由于可以使用另一个承诺(将进一步推迟其解析)来解决承诺,因此可以在链中的任何点暂停/推迟承诺的解析。这使得实现强大的API成为可能。 1

总结一下: $q服务用于创建承诺,因此在使用服务时(例如$http$timeout$resource等已经返回承诺,你通常不需要使用$q服务。

答案 2 :(得分:0)

$http执行异步调用。因此,理想情况下,如果您想在网址中获取响应的值,您应该使用' $范围'变量来存储它。

   $http("your url").then(function(response){
      //This is the success callback
      $scope.movies = response.data;
      });

答案 3 :(得分:0)

在这种情况下,您肯定不需要它,因为$http.get本身会返回一个承诺。但是,例如,如果您仅在某些条件下执行异步调用,那么它很有用

function acyncService () {
  if (dataLoaded) return $q.resolve(data);
  return $http.get('path/to/load/data');
}

在这种情况下,即使您不执行异步调用,您仍然可以使用

acyncService().then(function(data){
  console.log(data);
});

这只是许多例子中的一个。例如,当您与其他lib(例如$q promises)进行异步请求时,使用AWS SDK也很有用。