如果你想创建一个只需要通过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;
});
};
答案 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
也很有用。