如何使用 RESTful API 分页以按顺序获取 AngularJS 中的所有记录
How to consume a RESTful API with pagination to fetch all records sequentially in AngularJS
我正在消费的 API 提供了 link headers 这样的:
</resource?page=1&limit=10>; rel="next",
</resource?page=1&limit=10>; rel="last",
</resource?page=0&limit=10>; rel="first"
我需要在循环中一次消耗 /resource
端点 10 objects,直到 link [=30] 中不再有 next
=](最后一页)。
我有这样的资源:
myResources.factory('MyResource', [
'$resource',
function($resource) {
const ENDPOINT = '/api/resource/:id';
return $resource(ENDPOINT, null, {
query: {
method: 'GET',
isArray: true,
interceptor: {
response: function(response) {
response.resource.headers = response.headers;
return response.resource;
}
}
}
});
}]);
我有这样的服务:
myServices.factory('MyResourceService', [
function(MyResource) {
return {
findResources: function(){
return MyResource.query().$promise;
},
findAllResources: function(){
// I need to return a promise which will fetch all
// results from the server synchronously
var hasNext = true;
var params = {limit: 10, page: 0};
var chain = $q.all();
while(hasNext){
chain = chain.then(function(){
return MyResource.query(params).then(function(res){
var next = linkHeaderParser.parse(res.headers('link').next);
if(next) params = {limit: next.limit, page: next.page};
else hasNext = false;
}, function(){
hasNext = false;
});
});
}
return chain;
},
...
};
}]);
好吧,你的眼睛可能会受伤,因为我知道这不是实现此目的的正确方法,因为 hastNext
在 promise 实际执行之前不会更新,这会导致无限循环。但我无法理解它。感谢任何帮助,谢谢。
参考 by bigless,我是这样解决的:
var getResource = function(params){
return MyResource
.query(params)
.$promise;
};
// Method that extracts the last page
var pageCount = function(response){
var last =
linkHeaderParser.parse(response.headers('link')).last;
return parseInt(last.page);
};
params.limit = 0;
params.page = 0;
var deferred = $q.defer();
var resources = [];
// Method that extracts the last page
getResource(params)
.then(function(res){
var promises = [];
var lastPage = pageCount(res);
resources = resources.concat(res);
// Loop to get all pages
for(var i = params.page + 1; i <= lastPage; i++){
params.page = i;
promises.push(getResource(params));
}
return $q.all(promises);
}, function(err){
if(err.headers('x-pagination-count') &&
parseInt(err.headers('x-pagination-count')) === 0)
return $q.all([]);
}
})
.then(function(res){
// Concat results and resolve the promise
for (var i = 0; i < res.length; i++){
resources = resources.concat(res[i]);
}
deferred.resolve(resources);
});
我正在消费的 API 提供了 link headers 这样的:
</resource?page=1&limit=10>; rel="next",
</resource?page=1&limit=10>; rel="last",
</resource?page=0&limit=10>; rel="first"
我需要在循环中一次消耗 /resource
端点 10 objects,直到 link [=30] 中不再有 next
=](最后一页)。
我有这样的资源:
myResources.factory('MyResource', [
'$resource',
function($resource) {
const ENDPOINT = '/api/resource/:id';
return $resource(ENDPOINT, null, {
query: {
method: 'GET',
isArray: true,
interceptor: {
response: function(response) {
response.resource.headers = response.headers;
return response.resource;
}
}
}
});
}]);
我有这样的服务:
myServices.factory('MyResourceService', [
function(MyResource) {
return {
findResources: function(){
return MyResource.query().$promise;
},
findAllResources: function(){
// I need to return a promise which will fetch all
// results from the server synchronously
var hasNext = true;
var params = {limit: 10, page: 0};
var chain = $q.all();
while(hasNext){
chain = chain.then(function(){
return MyResource.query(params).then(function(res){
var next = linkHeaderParser.parse(res.headers('link').next);
if(next) params = {limit: next.limit, page: next.page};
else hasNext = false;
}, function(){
hasNext = false;
});
});
}
return chain;
},
...
};
}]);
好吧,你的眼睛可能会受伤,因为我知道这不是实现此目的的正确方法,因为 hastNext
在 promise 实际执行之前不会更新,这会导致无限循环。但我无法理解它。感谢任何帮助,谢谢。
参考
var getResource = function(params){
return MyResource
.query(params)
.$promise;
};
// Method that extracts the last page
var pageCount = function(response){
var last =
linkHeaderParser.parse(response.headers('link')).last;
return parseInt(last.page);
};
params.limit = 0;
params.page = 0;
var deferred = $q.defer();
var resources = [];
// Method that extracts the last page
getResource(params)
.then(function(res){
var promises = [];
var lastPage = pageCount(res);
resources = resources.concat(res);
// Loop to get all pages
for(var i = params.page + 1; i <= lastPage; i++){
params.page = i;
promises.push(getResource(params));
}
return $q.all(promises);
}, function(err){
if(err.headers('x-pagination-count') &&
parseInt(err.headers('x-pagination-count')) === 0)
return $q.all([]);
}
})
.then(function(res){
// Concat results and resolve the promise
for (var i = 0; i < res.length; i++){
resources = resources.concat(res[i]);
}
deferred.resolve(resources);
});