我有一个返回$ http promises的服务。这工作正常,但我需要做一个递归调用,以防列表返回超过100个项目。再次,这可行,但我为每个控制器重复自己。我无法将递归卸载到服务并仍然获得最终结果。也许$q
会有帮助吗?
// service
function List ($http) {
var headers = {'Accept': 'application/json;odata=verbose'}
, listService = {
getByName: function (listName) {
return $http({
method: 'GET'
, url: '/_api/web/lists/getByTitle(\'' + listName + '\')/items'
, headers: headers
});
}
, getByUrl: function (url) {
return $http({
method: 'GET'
, url: url
, headers: headers
})
}
};
return listService;
}
// controller
function Calendar ($scope, List) {
$scope.events = [];
List.getByName('Calendar').success(function (response) {
$scope.events = response.d.results;
if (response.d.__next) {
List.getByUrl(response.d.__next).success(recursiveSuccess);
}
});
function recursiveSuccess (response) {
$scope.events = $scope.events.concat(response.d.results);
if (response.d.__next) {
List.getByUrl(response.d.__next).success(recursiveSuccess);
}
}
}
答案 0 :(得分:0)
由于每次调用都会为您提供下一个端点的URL,因此必须在连续的HTTP调用中完成。就承诺而言,它将在概念上如此完成:
return firstCall.then(function(data){
return secondCall(data);
})
// another .then
// another .then
.then(function(data){
return lastCall(data);
});
这里的每个NCall
都是一个函数,它接收上一个调用的数据并返回下一个聚合数据的承诺,lastCall
返回最终的聚合数据。
如果要将其转换为递归函数,它将如下所示:
function getItemsFrom(url, items){
return $http.get(url).then(function(response){
items = items.concat(response.data.items);
if (response.data.next){
return getItemsFrom(response.data.next, items);
} else {
return items;
}
});
}
数据为:
{
"next": "url/to/data2.json",
"items": [1, 2, 3]
}
唯一剩下的就是初次通话:
.factory("fooSvc", function($http){
function getItemsFrom(url, items){
// as above
}
return {
getItems: function(){
return getItemsFrom("url/to/data1.json", []);
}
};
});
答案 1 :(得分:0)
是的,我遇到了类似的问题,我必须在我的服务中的方法中进行多次调用,并使用$q
解决了问题。一旦你学会了如何使用它,它就会非常强大。
在您的服务方式中:
function promiseYoullCallMeWhenYoureComplete () {
var deferred = $q.defer();
var events = [];
startMyQuery();
return deferred.promise;
////////////
function startMyQuery () {
List.getByName('Calendar').then(success, error);
}
function success (response) {
// perform success actions
events = angular.extend(events, response.data.d.results);
// run next query or exit if complete
if (response.data.next) {
return startMyQuery();
}
// no more queries, so exit and return my combined events array
return deferred.resolve(events);
}
function error (response) {
return deferred.reject(response);
}
}
然后在您的控制器中,例如:
List.promiseYoullCallMeWhenYoureComplete().then(success, error);
///////////
function success (events) {
$scope.events = events;
}
function error (response) {
console.error("Error:", response);
}
通过这种方式,您的服务可以进行$ http查询,直到奶牛回家,但您的控制器只会收到一个响应来处理(要么成功,所有结果都会通过您的{{1因为你可以将所有逻辑移动到服务中,所以你的控制器非常干净。