A common problem working with ajax is firing duplicate requests. A common solution is to first check if a request is ongoing. I solved this problem differently by memoizing the get request for the lifetime of the request.
Memoization is storing the results of a function call and returning the cached result when the same inputs occur. This is often used to optimize expensive function calls, but I see value in using it here. In the code below we use Restangular, but the concept works just as well for any promise based request library.
function memoizedService(route) { var service = Restangular.service(route); var hasher = JSON.stringify; var memoizedGetList = _.memoize(service.getList, hasher); /** * Get list, but if there already is a request ongoing with the same * params then return the existing request. * @param {Object} params * @return {promise} */ service.getList = function(params) { return memoizedGetList(params).finally(function() { delete memoized.cache[hasher(params)]; }); } return service; } var questionEndpoint = Restangular.memoizedService('question');
Make sure you install underscore with a bit of
bower install underscore --save
Then, to use the feature we would do:
questionEndpoint.getList({page: 1});
If we request page 1 when there is already a request for page 1 then the second `getList` will return the same promise that the first request returned and you will only see 1 request for page 1 in the network panel. Note importantly we also remove the cached request when the request is complete. This prevents data consistency problems: a get request can return different data over time (e.g., more records), and we want to make sure the user receives the most up to date data.