I have a "cancellable" angularJs $http
call like this:
var defer = $q.defer()
$http.post("http://example.com/someUrl", {some: "data"}, {timeout: defer.promise})
And I cancel that ajax request using defer.resolve()
because some logic requires it.
Some where else in my code, I have an iterceptor like this:
angular.module("services.interceptor", arguments).config(function($httpProvider) {
$httpProvider.interceptors.push(function($q) {
return {
responseError: function(rejection) {
if(rejection.status == 0) {
alert("check your connection");
}
return $q.reject(rejection);
}
};
});
});
});
If there is an Internet connection problem, ajax fails with status 0 and interceptor catches it. If ajax is cancelled by the timeout promise, than status is also 0 and interceptor catches it.
I can't find out if it is cancelled or got error in responseError
handler.
My naive approach is to check if timeout is defined like this:
responseError: function(rejection) {
if(rejection.status == 0 && !rejection.config.timeout) {
alert("check your connection");
}
return $q.reject(rejection);
}
It only guarantees that, there is a timeout condition on that request, not it failed because of it. But it is better than nothing.
Are there a really working way of determining if ajax is failed or cancelled?
I'm using AngularJs 1.1.5
I ended up doing this using a flag, which is checked within the error handler.
I started off following the advice at the end of this AngularJS Github issue: https://github.com/angular/angular.js/issues/1159#issuecomment-25735438
This led me to build a service which used a promise to manually "timeout" the http call - as you have done below - by copying the linked plunk from that issue: http://plnkr.co/edit/P8wKns51GVqw5mwS5l5R?p=preview
But this wasn't quite complete, as this didn't address the issue you raised; in the error handling, how to determine if the call was a genuine server outage / timeout, or simply a manually triggered timeout. In the end, I had to resort to storing it in another variable (similar to the timeout promise), which can be seen in this plunk: http://plnkr.co/edit/BW6Zwu
The main method of this code looks as follows
return function (url) {
var cancelQuery = null;
var queryCancelled = false;
return function runQuery(query) {
if (cancelQuery) {
queryCancelled = true;
cancelQuery.resolve();
}
cancelQuery = $q.defer();
return $http.
get(url, { params: { query: query }, timeout: cancelQuery.promise }).
then(function (response) {
cancelQuery = null;
return response.data;
}, function (error) {
if(queryCancelled) {
console.log("Request cancelled");
queryCancelled = false;
} else {
console.log("Actual Error !");
}
});
};
};
Not too elegant, but it seems to work and avoids any nasty race conditions from what I have observed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With