XHR.statusText error when aborting angular $http requests - angularjs

So I have recently implemented a means to cancel an $http request via the timeout property by passing in and resolving a promise.
When a request is aborted the $http promise goes to the error block. This is all fine, its after this all finishes processing I receive an error from angular.js (xdomain.js is in the call stack) stating that it "Cannot read property 'statusText' of null". Null being the xhr object.
I'm at a loss currently as the request is successfully being cancelled, but it seems as if the xhr object is being destroyed right after calling xhr.onload().
Here's an example of how I'm cancelling the request:
var request = {
url: 'someurl',
method: 'get',
headers: headers
timeout: canceller // this is a promise that I resolve in a controller in order to abort an $http request. This works fine.
}
$http(request).then(function () {
//success block
}, function () {
// error block
});
As I said, it enters the error block but it isn't inside of that block that the angular error is thrown, rather it seems to be with the request comes back and there is no longer an xhr object waiting for it that an error occurs.

This is a common problem with Angular and Xdomain. A workaround I'm fond of is passing in a unique identifier or bool when submitting the request. If the value has changed when the request is completed simply ignore the results.

Related

Unable to figure out what's happening here in $http.get - Angular

I'm a newbie to Angular JS. I was referring Online tutorials and came across the $http service.
(function () {
"use strict";
angular
.module("ngClassifieds") // referring module which is already created
.controller("classifiedsCtrl", function ($scope, $http) {
$http.get('data/classifieds.json')
.then(function(classifieds){
$scope.classifieds = classifieds.data;
})
});
})();
In this piece of code, I'm not able to figure out these lines. Can
anyone explain what actually happens here ?
$http.get('data/classifieds.json')
.then(function(classifieds){
$scope.classifieds = classifieds.data;
}
I have this data in my data/classifieds.json file.
My question is, what exactly the data referred in classifieds.data is ?
what does classifieds.data represent here ?
what information does it contain?
what would be the result which we assign to $scope.classifieds?
$http returns a promise, it's an asynchronous call, angular use a fork of a library called Q for promises, you can see $q documentation here: https://docs.angularjs.org/api/ng/service/$q.
When the promise is fulfilled, that means, the asynchronous call is complete, the .then method call success or error callback depending on the result of the async call.
.then(successCallback, [errorCallback], [notifyCallback]) – regardless
of when the promise was or will be resolved or rejected, then calls
one of the success or error callbacks asynchronously as soon as the
result is available. The callbacks are called with a single argument:
the result or rejection reason. Additionally, the notify callback may
be called zero or more times to provide a progress indication, before
the promise is resolved or rejected.
The argument passed to the success callback is an object with the information about the request response. The data property contain the body of the response, in other way, all the content of data/classifieds.json file (in your case), therefore, $scope.classifieds will contain the json returned by data/classifieds.json.
Here a friendly article about promises and $q: http://www.dwmkerr.com/promises-in-angularjs-the-definitive-guide/
A simple get request example from AngularJS Docs.
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
In your code,
$http.get('data/classifieds.json') // This is the URI of your json file
.then(function(classifieds){ // Success callback
$scope.classifieds = classifieds.data; // Here, you are assigning response's data into $scope.classifieds
}

Ionic/AngularJS $resource Timeout Config Setting Not Working

I've been trying to setup a timeout value (in milliseconds) for my $resource so that if the server doesn't respond within 10*1000 milliseconds, I want the service in my factory to return the error promise.
I have a factory with the following method:
service.getDelta = $resource(BASE_API_URL + '/delta/:inTable/:inDate',
{inTable: '#inTable', inDate: '#inDate'},
{query: {timeout: 10*1000}});
In the controller I do the following:
getDataPromises.push(remoteService.getDelta.query({inTable: "table1", inDate: clientDateLastModified}).$promise);
getDataPromises.push(remoteService.getDelta.query({inTable: "table2", inDate: clientDateLastModified}).$promise);
getDataPromises.push(remoteService.getDelta.query({inTable: "table3", inDate: clientDateLastModified}).$promise);
getDataPromises.push(remoteService.getDelta.query({inTable: "table4", inDate: clientDateLastModified}).$promise);
Then I check to ensure all are successful or handle error if one fails.
$q.all(getDataPromises).then(
function (result) {
// NOTIFY SUCCESS
},
function (error) {
// NOTIFY ERROR
});
The success in the promise has been coming through as expected. If I leave out the timeout config, I also get the error in the promise for issues like 404. But when I add the timeout, I get the following when I stringify the error object in my error callback:
{"line":13380,"column":32,"sourceURL":"file:///Users/ ... /www/lib/ionic/js/ionic.bundle.js"}
Am I misunderstanding the use of the timeout property?
I am using ionic 1.2.4 which I believe is using Angular 1.4.3.
Note: I know this use case doesn't justify use of $resource and could be done with $http, but I wanted to get to get a feel for using it since I plan to down the road for this app.
Thanks!

Why does angularjs discard the message response for http status codes <200 && >300?

I've been tracking down the reason why I cannot see the response from my webapi in angularjs using $http if the status code is less than 200 and greater than 300.
I've debugged angular.js to the point where I understand whats happening (basically its discarding the promise that contains the data i care about and creating a new one without it if the status codes are not deemed a success)
-see code at https://github.com/angular/angular.js/blob/master/src/ng/q.js#L270-L280
this.$$state.value (holds the http respone) is lost at this point for some reason.
Does it make sense to omit the original values? I'm not going to submit a bug report without asking here if I'm right or wrong.
The reason behind all this is that I am processing some credit card info on the server side. If the processor says its an invalid card, I wouldn't think it would be a 200 code, would it? See the answer to this question..... Suggesting 400 for business rules. This still fails in angularjs.
What is the appropriate HTTP status code response for a general unsuccessful request (not an error)?
Also, FYI, httpInterceptors do not work either, since they are utilized after this 'promise replacement' occurs.
From the Docs:
A response status code between 200 and 299 is considered a success status and will result in the success callback being called. Any response status code outside of that range is considered an error status and will result in the error callback being called.
— AngularJS $http Service API Reference - General Usage
The $http service rejects responses outside of the range of 200 to 299 but it does not "discard the message response". Both the resolve and the reject methods of the $http promise are invoked with the entire response object.
This means all of the data is available in the rejection handler.
var dataPromise = $http(configObject)
.then (function onFulfilled(response) {
//return data for chaining
return response.data;
})
.catch (function onRejected(response) {
if (response.status == 400) {
console.log("400 Bad Request");
console.log("REASON:", response.data);
//chain with default data
return defaultData;
} else {
//throw to chain rejection
throw response;
}
});
In the above example, the rejection handler logs the response for messages with status 400 and converts the rejection to fulfilled with default data. All other status responses get chained as a rejection.
Data is not discarded; it is available and can be used in the rejection handler.
For more information on chaining promises, see Angular execution order with $q.
Do you write status codes when you use promise callbacks then, catch and finally after the $resource call.
Here is what I would check for :
MyRestAPI.XXX({resource}, {data}, MyCallbackFunction).$promise.catch(function(response) {
//should be called upon error
//check response.status for HTTP code.
}).then(function() {
// OK
});

Abort JSONP request AngularJs

I have the following code:
var canceler = $q.defer();
$http.jsonp(urlWithParams, {
timeout : canceler.promise
}).error(function(data, status, headers, config) {
...
}).success(function(data) {
...
}
});
canceler.resolve();
The error handler of the request gets executed however in the network log of both Firefox and Chrome give 200 responses and return the JSON response. So while the application behaves like the request was aborted, in reality it wasn't? When canceling the request I would have expected the request to have been aborted than returning a 200 success.
You're not doing anything wrong.
Generally, because http is stateless, you can't abort a request once it's been sent to the server. You can, however, stop waiting for and ultimately ignore an eventual response - as you are doing here.
Unless you feel that the error handler shouldn't have been fired because the response succeeded? You don't say whether you're concerned that it was incorrectly failed, or that the aborted request received a response.
The final statement in your code canceler.resolve() will trigger the error. From the angularjs docs:
timeout – {number|Promise} – timeout in milliseconds, or promise that should abort the request when resolved.
So I think if you don't call canceler.resolve() it won't call the error function.

Ext.Ajax.request() invokes the failure callback function upon successful request

I'm building a PhoneGap - Sencha-touch application for the iOS and Android platforms. I am loading a local .js file using the Ext.Ajax.request() function.
Funny thing happens - the requests succeeds, but the the 'failure' callback is called.
Here is the code:
Ext.Ajax.request({
url: 'localfolder/foo.js',
success : function(xhr){
// not invoked
},
failure : function(response, options){
// response.status == 0
// wtf, response.responseText contains exactly the contents of the local .js file!
}
});
Anyone has an Idea why the 'failure' callback is triggered when in fact the request succedded?
[edit]
More importantly, how do I make the 'success' callback to be triggered instead?
Ext.Ajax simply examines the status code of the underlying XHR (XmlHttpRequest) object it creates. However, it (incorrectly) assumes that the status is an HTTP status. As this Mozilla-provided article discusses, when file: or ftp: schemes are used, a status value of 0 indicates success.
You can modify the onComplete function in Ext.data.Connection (in src/data/Connection.js) to look at the scheme of the URL, and decide if it should use an HTTP-based status or a "0=OK" status to determine success.
It is perfectly legal for non-success results to have a body that can be used by the client. This is why your response.responseText still shows up correctly.
I usually using response like this, maybe it'll help
{
success:true, // success status
data: [] // data from process
}

Resources