On route change, I need to abort ALL pending requests from previous route so that I don't run into problems of responses from previous route messing up data on my current route (it happens sometimes when responses from previous route take long time to finish).
I have thought about using http interceptor for this:
$httpProvider.interceptors.push(function($q) {
return {
'request': function(config) {
},
'response': function(response) {
}
};
});
In the request function, I could modify the config.timeout
with a promise as suggested here and store all the deferred objects in a global cache so that I could cancel all of them.
The problem with this approach is that it may override config.timeout
set in other places in the code.
I think another solution could be to cancel all ajax requests at XMLHttpRequest
level, but I don't know how to do it.
Any suggestions? Thanks.
On route change, I need to abort ALL pending requests from previous route so that I don't run into problems of responses from previous route messing up data on my current route (it happens sometimes when responses from previous route take long time to finish).
I have thought about using http interceptor for this:
$httpProvider.interceptors.push(function($q) {
return {
'request': function(config) {
},
'response': function(response) {
}
};
});
In the request function, I could modify the config.timeout
with a promise as suggested here and store all the deferred objects in a global cache so that I could cancel all of them.
The problem with this approach is that it may override config.timeout
set in other places in the code.
I think another solution could be to cancel all ajax requests at XMLHttpRequest
level, but I don't know how to do it.
Any suggestions? Thanks.
Share Improve this question edited May 23, 2017 at 12:18 CommunityBot 11 silver badge asked Aug 14, 2014 at 5:07 Khanh TOKhanh TO 49k13 gold badges101 silver badges116 bronze badges 6-
If the
config.timeout
is already set in other place, you could still bine it with the promise for this purpose together. – runTarm Commented Aug 14, 2014 at 5:15 -
Even if there was a built in way to cancel all pending
XMLHttpRequest
s wouldn't it cause trouble by i.e. not loading html templates. Furthermore it's very mon to have an fire&forget action which you don't want to cancel even though you've moved to another screen... – miensol Commented Aug 14, 2014 at 5:18 -
@runTarm: how to do it? Anyway, I think that
timeout
is another concept separated fromabort
. It's a trick when we take advantage oftimeout
to abort a request (we should avoid tricks when coding). – Khanh TO Commented Aug 14, 2014 at 5:51 - @miensol: it would not cause trouble not loading html because I've moved to another route. I'm working on an existing code base, I cannot just fire&forget, this is causing problems in the app. – Khanh TO Commented Aug 14, 2014 at 5:54
- 1 @runTarm: I think I agree with the second answer from the link in the question: stackoverflow./questions/13928057/… – Khanh TO Commented Aug 14, 2014 at 6:10
1 Answer
Reset to default 7As you say, timeout
is the only API we have of use right now to cancel a running $http request. I think you're right on the money with an interceptor coupled with a cancel promise.
What you could do is attach the full deferred object on the $http
request, and cancel all pendingRequests in your route change handler.
Something like this could (perhaps*) work?
angular.module('module').config(function ($httpProvider) {
$httpProvider.interceptors.push(function ($q) {
return {
request: function (config) {
if (!config.timeout) {
config.cancel = $q.defer();
config.timeout = config.cancel.promise;
}
return config;
}
}
});
});
angular.module('module').run(function ($rootScope, $http) {
$rootScope.$on('$stateChangeStart', function () {
$http.pendingRequests.forEach(function (pendingReq) {
if (pendingReq.cancel) {
pendingReq.cancel.resolve('Cancel!');
}
});
});
});
*: I say perhaps, because I had success with this approach, but it's seldom you find a silver bullet to something like this.
edit
If you need to bypass the error handler of the cancelled promise, hook into responseError
property and do manual labour there.
angular.module('module').config(function ($httpProvider) {
$httpProvider.interceptors.push(function ($q) {
return {
responseError: function (response) {
if (response.config.timeout.$$state.value === 'Cancel!') {
// debugger;
return $q.when('bypassed');
}
}
}
});
});
I'm starting to think that there is no generic/'cool' solution to reach the end result you desire. Treading some odd ground here : )
edit2:
Testing the above myself now. Returning $q.when('something')
in the responseError
will effectively bypass the error callback of the cancelled $http
request. Let me know if it works out for you.