Skip to content

Instantly share code, notes, and snippets.

@azurelogic
Last active February 25, 2016 21:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azurelogic/31c29aa3747d8d87b842 to your computer and use it in GitHub Desktop.
Save azurelogic/31c29aa3747d8d87b842 to your computer and use it in GitHub Desktop.
Wrapper for Angular's $http that supports easy cancellation of requests (ES6)
(function () {
angular.module('yourModule')
.decorator('$http', httpConfig);
// Uses the following libs:
// angular-cache: https://github.com/jmdobry/angular-cache
// lodash: https://lodash.com/
// node-uuid: https://github.com/broofa/node-uuid
// I wrap lodash and node-uuid in their own services separately
httpConfig.$inject = ['$delegate', '$q', '$timeout', 'CacheFactory', '_', 'uuid'];
function httpConfig($delegate, $q, $timeout, CacheFactory, _, uuid) {
let cache = CacheFactory.get('httpCancellation');
if (!cache)
cache = CacheFactory('httpCancellation', {});
let _http = $delegate;
$delegate = (config, cToken) => executeRequest(null, null, config, undefined, cToken);
$delegate.$base = _http;
$delegate.get = (url, config, cToken) => executeRequest('GET', url, config, undefined, cToken);
$delegate.delete = (url, config, cToken) => executeRequest('DELETE', url, config, undefined, cToken);
$delegate.head = (url, config, cToken) => executeRequest('HEAD', url, config, undefined, cToken);
$delegate.jsonp = (url, config, cToken) => executeRequest('JSONP', url, config, undefined, cToken);
$delegate.post = (url, data, config, cToken) => executeRequest('POST', url, config, data, cToken);
$delegate.put = (url, data, config, cToken) => executeRequest('PUT', url, config, data, cToken);
$delegate.patch = (url, data, config, cToken) => executeRequest('PATCH', url, config, data, cToken);
$delegate.cancel = cancel;
$delegate.cleanUp = cleanUp;
$delegate.cancelAllRequests = cancelAllRequests;
function executeRequest(methodName, url, config, data, cancellationToken) {
let requestConfig = config || {};
if (methodName) {
requestConfig.method = methodName;
}
requestConfig.data = data;
requestConfig.url = url;
let cancellationDeferred = $q.defer();
if (requestConfig.timeout) {
if (_.isNumber(requestConfig.timeout))
$timeout(() => cancellationDeferred.resolve(), requestConfig.timeout);
else if (requestConfig.timeout.then && requestConfig.timeout.catch) {
requestConfig.timeout.then(() => cancellationDeferred.resolve());
requestConfig.timeout.catch(() => cancellationDeferred.reject());
}
}
requestConfig.timeout = cancellationDeferred.promise;
let requestPromise = _http(requestConfig);
let newUuid = uuid.v4();
if (cancellationToken && _.isObject(cancellationToken)) {
if (!cancellationToken.uuids || !_.isArray(cancellationToken.uuids))
cancellationToken.uuids = [];
cancellationToken.uuids.push(newUuid);
}
cache.put(newUuid, {cancellationDeferred});
requestPromise.then(() => cleanUp({uuids: [newUuid]}));
requestPromise.catch(() => cleanUp({uuids: [newUuid]}));
return requestPromise;
}
function cleanUp(cancellationToken) {
if (!cancellationToken || !cancellationToken.uuids) return;
_.forEach(cancellationToken.uuids, x => {
let cacheRecord = cache.get(x);
if (cacheRecord && cacheRecord.cancellationDeferred) {
cacheRecord.cancellationDeferred.reject();
cache.remove(x);
}
});
}
function cancel(cancellationToken) {
if (!cancellationToken || !cancellationToken.uuids) return;
_.forEach(cancellationToken.uuids, x => {
let cacheRecord = cache.get(x);
if (cacheRecord && cacheRecord.cancellationDeferred) {
cacheRecord.cancellationDeferred.resolve();
cache.remove(x);
}
});
}
function cancelAllRequests() {
_.forEach(cache.values(), x => {
if (x && x.cancellationDeferred && x.cancellationDeferred.resolve)
x.cancellationDeferred.resolve();
});
cache.removeAll();
}
return $delegate;
}
})();
@azurelogic
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment