我是angular的$ q的新手,我正在尝试构建一个API调用服务并将其返回给控制器。
问题:无论我如何格式化它,服务returns
就在它到达$ http.get(...)之前
服务:
// methods: query new, get existing
makeRequest: function(url, following) {
// create promise
var deferred = $q.defer();
$http.get(url, {
params: {
"following": JSON.stringify(following)
}
})
.then(function(res) {
console.log(res);
deferred.resolve(res.data);
});
return deferred.promise;
},
getFeed: function(user) {
console.log('>> userService[getUser]: retrieving user...');
if (!this.activities) {
// Request has not been made, setting user profile.
console.log('>> userService[getUser]: No user stored, making request...');
var following = this.compileArray(user);
console.log(following);
this.activities = this.makeRequest('api/network/activities', following);
};
// Return the myObject stored on the service
return this.activities;
}
控制器
$scope.recentActivity = activityService.getFeed(profile);
// also tried
activityService.getFeed(profile).then(function (res) {
$scope.recentActivity = res;
console.log(res);
});
编辑:2015年6月5日上午9:40
如果可能的话,我想从服务中检索控制器中的活动列表,就像它是新的一样(使用.then
)。这是可能/不好的做法吗?
getFeed: function(user) {
if (!this.activities) {
...
} else {
feedPromise = $q(function(resolve){ resolve(this.activities) });
console.log(feedPromise);
// returns: {$$state: Object, then: function, catch: function, finally: function}
feedPromise.then(function(res) {
console.log(res);
// returns: undefined
});
console.log(that.activities);
// Works, returns list of activities.
}
答案 0 :(得分:5)
除非您使用回调将基于非承诺的API转换为基于承诺的API,否则无需使用$q.defer
(即便如此,建议使用$q(function(resolve, reject){...})
)。
$http
已经返回一个承诺 - 只需返回 (或链式.then
承诺);
var httpResponsePromise = $http.get(url); // returns a promise
var actualDataPromise = httpResponsePromise.then(function(resp){ return resp.data; });
return actualDataPromise;
或更短(和典型):
return $http.get(url).then(function(response){
return response.data;
});
其次,承诺返回的API会同步返回承诺 - 而不是结果 - 马上。您需要.then
才能获得结果。
最后,一旦API是异步的,它应始终是异步的 - 不要将其转换为同步或有时同步API。因此,无论在哪里,一直到数据的最终收件人,您都需要使用.then
处理程序。
因此,您的服务API可以非常简单:
makeRequest: function(url, following){
return $http.get(url, {params: { "following": following }})
.then(function(response){
return response.data;
});
},
getFeed: function(user) {
var that = this;
var feedPromise;
if (!that.activities) {
var following = this.compileArray(user);
feedPromise = this.makeRequest('api/network/activities', following)
.then(function(activities){
that.activities = activities;
return activities;
});
} else {
feedPromise = $q(function(resolve){ resolve(that.activities); });
// or you could have cached the old feedPromise and returned that
}
return feedPromise;
}
控制器中的用法与任何其他基于承诺的API一样:
activityService.getFeed(profile)
.then(function(activities) {
$scope.recentActivity = activities;
});
答案 1 :(得分:0)
在了解@New Dev的评论中指出的deferred anti-pattern之后,我编辑了这个答案。有关详细说明,请参阅@New Dev的答案。谢谢@New Dev。
<强>服务强>
makeRequest: function(url, following) {
return $http.get(url, {
params: {
"following": JSON.stringify(following)
}
}).then(function(res) {
return res.data;
});
},
getFeed: function(user) {
var that = this;
if (!that.activities) {
var following = that.compileArray(user);
return that.makeRequest('api/network/activities', following)
.then(function(activities){
that.activities = activities;
return that.activities;
});
} else {
return $q(function(resolve) {
resolve(that.activities);
});
}
}
<强>控制器强>
activityService
.getFeed(profile)
.then(function (activities) {
$scope.recentActivity = activities;
});
答案 2 :(得分:-1)
我认为如果你想拥有响应对象,你需要使用.success而不是.then。
$http.get(url, {
params: {
"following": JSON.stringify(following)
}
})
.success(function(res) {
console.log(res);
deferred.resolve(res.data);
});