The API I am consuming provides with the link headers as such:
</resource?page=1&limit=10>; rel="next",
</resource?page=1&limit=10>; rel="last",
</resource?page=0&limit=10>; rel="first"
And I need to consume the /resource
endpoint, 10 objects at a time, in a loop, until there's no more next
in link headers (last page).
I have a resource as such:
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;
}
}
}
});
}]);
and I have a service as such:
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;
},
...
};
}]);
Well, your eyes might hurt, because I know this is not the proper way to achieve this, since hastNext
is not updated before the promise is actually executed, this leads to an infinite loop. But I couldn't get my head around it. Any help appreciated, thanks.
With reference to the comment by bigless, this is how I solved it:
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);
});