`xhr`, `status` and `ex` variables in a jQuery AJAX request - javascript

I am using jQuery 1.6 and I would like to know and understand how I can access response xhr, status and ex variables in the following code:
$jQuery.ajax({
type: "POST",
url: "<some_url>",
error: function(xhr, status, ex) {
var msg = "";
if (xhr) {
msg = "readyState is " + xhr.readyState + ". ";
}
if (ex) {
msg += ex.name + ' - ' + ex.message;
}
alert("ERROR " + msg); }
success: function(jqXHR, status, ex) {
...
}
});
How can I know the full list of all them "accessible" values like, for example, readyState for the xhr (xhr.readyState), name and message for the ex (ex.name and ex.message)?
Moreover, what xhr and ex variables represent (I think status refers to the HTTP status code)?

I strongly suggest you to have a look at the docs.
Here an example.
error(jqXHR, textStatus, errorThrown)Function
A function to be called if the request fails. The function receives three arguments: The jqXHR (in jQuery 1.4.x, XMLHttpRequest) object, a string describing the type of error that occurred and an optional exception object, if one occurred. Possible values for the second argument (besides null) are "timeout", "error", "abort", and "parsererror". When an HTTP error occurs, errorThrown receives the textual portion of the HTTP status, such as "Not Found" or "Internal Server Error." As of jQuery 1.5, the error setting can accept an array of functions. Each function will be called in turn. Note: Prior to jQuery 1.5, this handler was not called for cross-domain script and JSONP requests. This is an Ajax Event
jQuery has a very good documentation. The docs should be the first place to look at, for questions like yours. If you encounter problems while implementing jQuery you are welcome to ask at SO.

Related

Unable to handle scenario: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access

I have a form on a webpage which I'm using to capture data and post to a Google Form. The code I've used I saw on this answer. Now, as expected, I'm receiving an error like the following:
XMLHttpRequest cannot load
https://docs.google.com/forms/d/.../formResponse.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access.
My script making the request is as follows:
function postToGoogle() {
$.ajax({
url: "https://docs.google.com/forms/d/.../formResponse",
data: {"entry.1691469052": "test message"},
type: "POST",
dataType: "xml",
success: function() {
alert("Success");
},
error: function() {
alert("Error");
}
});
}
$(document).ready(function(){
$('#form').submit(function() {
postToGoogle();
return false;
});
});
Now even though I get the error, my data still persists to the form which is the outcome I want.
The issue I'm facing is that in the event that data is passed, I want to display a message to the user saying the data was received. What I'm trying to do is either:
fix the error through using CORS or similar (methods I'm not familiar with and can't find an answer for on SO)
somehow check within my 'error' function that the only issue is the No 'Access-Control-Allow-Origin' one and then produce a 'success' message in that scenario. If there are other issues I'll just throw an 'error' message back to the user
So far I've not been able to find something that works. Any thoughts?
See the $.ajax doc:
error
Type: Function( jqXHR jqXHR, String textStatus, String errorThrown )
A function to be called if the request fails. The function receives three arguments: The jqXHR (in jQuery 1.4.x, XMLHttpRequest)
object, a string describing the type of error that occurred and an
optional exception object, if one occurred. Possible values for the
second argument (besides null) are "timeout", "error", "abort", and
"parsererror". When an HTTP error occurs, errorThrown receives the
textual portion of the HTTP status, such as "Not Found" or "Internal
Server Error."
So you can write something like:
error: function( jqXHR, textStatus, errorThrown ) {
if( errorThrown.indexOf("Access-Control-Allow-Origin") > 0 ) {
// success...
}
The error text can also be inside jqXHR.responseText.

Proper way to nest error messages while making asynchronous requests

When I make a synchronous jQuery ajax request, I need the ability to delay displaying the error message to the user until I can add some more information that does not exist in the context of my error function. I'm trying to find a way to throw the information collected about the exception so that it can be caught higher up the chain and and be displayed with more meaningful information to the user. I'm finding that even with synchronous requests, when I put a throw statement inside my error function that it is not caught by my wrapping catch block.
function GetFileName(entity, field, guid){
var filename;
try
{
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
datatype: "json",
url: myURLwashere,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Accept", "application/json");
},
async: false,
success: function (data, textStatus, xhr) {
var result = data.d;
filename = result[field];
},
error: function (xhr, textStatus, errorThrown) {
throw textStatus + " " + errorThrown;
//entity, field and guid are null here
}
});
}
catch (err){
//this catch block does not catch the exception thrown by the error function.
throw "Error Getting File Name from web service for entity '" + entity + "' field '" + field + "' and guid '" + guid + "' (" + err.message + ")";
}
return filename;
}
This is a very simple example. I could be nested through several functions several layers deep and want to add to the error message multiple times before displaying it to the user.
Update
I've updated the question to reflect my end-goal (nested error handling) without requiring that the solution be synchronous, which has been discouraged.
I'm writing this in response to the Troy's question in the comments, "How about some recommendations for how to properly aggregate good error messages in nested calls with an asynchronous request instead?"
If you've not done much event-driven (asynchronous) programming before, it does take a little getting used to. Find yourself a good online tutorial like this one:http://code.tutsplus.com/tutorials/event-based-programming-what-async-has-over-sync--net-30027. If you're just starting out you might want to avoid getting into the Deferred or Promise model of asynchronous programming. Those are great tools, but callbacks are an easier way to start out.
One way to transform your code to be asynchronous is to give your function two extra "callback function" parameters:
function GetFileName(entity, field, guid, onSuccess, onError){
Now change async to true and modify the success and errors functions like this:
async: true,
success: function (data, textStatus, xhr) {
var result = data.d;
filename = result[field];
onSuccess( filename );
},
error: function (xhr, textStatus, errorThrown) {
// REMOVE: throw textStatus + " " + errorThrown;
//entity, field and guid are null here
onError(textStatus, errorThrown);
}
Then remove the catch block and the return statement.
This style will cause you to rework or maybe even redesign some of your current code base. But as others have pointed out, using synchronous ajax calls can create a really poor user experience.

errorThrown jquery error-callback function

What data is the parameter errorThrown (third parameter of jQuerys error callback function)
Is it something, that the server (backend one has written, in my case it is some REST-based services written in Java) has to return, or is it something more general, which is "automatically" returned without one has to add some error-handling in ones code?
Well, from jQuery.ajax()s documentation:
Type: Function( jqXHR jqXHR, String textStatus, String errorThrown )
... When an HTTP error occurs, errorThrown receives the textual portion of the HTTP status, such as "Not Found" or "Internal Server Error."...
So the errorThrown string coorseponds to the HTTP status response for any failure responses (>399) For a 400, it would be Bad Request, 500: Internal Server Error, etc...
Quote from the documentation:
error
Type: Function( jqXHR jqXHR, String textStatus, String
errorThrown ) A function to be called if the request fails. The
function receives three arguments: The jqXHR (in jQuery 1.4.x,
XMLHttpRequest) object, a string describing the type of error that
occurred and an optional exception object, if one occurred. Possible
values for the second argument (besides null) are "timeout", "error",
"abort", and "parsererror". When an HTTP error occurs, errorThrown
receives the textual portion of the HTTP status, such as "Not Found"
or "Internal Server Error." As of jQuery 1.5, the error setting can
accept an array of functions.
So basically the errorThrown parameter has nothing to do with the response sent from the server. It's just the error reason associated to the status code. If your server uses custom error reasons in addition to setting the status code, this parameter might be useful to retrieve it.
Something to note (I just ran into this) is that errorThrown will be an empty string for requests that were made with HTTP/2.
This is because the property comes from the statustext property of the underlying XHR, and that property does not get populated for HTTP/2 requests.
More info here:
Why is the statusText of my XHR empty?

Json Response is undefined

This is driving me nuts, I have been through every article I have seen on Google and here and two days later, 101 variants later I am still no further forward.
The success 201 works perfectly, I get an alert with bound items. The 404 doesn't work at all, no matter what I try the ErrorDesc is always undefined. I have got it working that it can hit this 404 function with a fixed string, but I want the user to know why there is an error.
I have used fiddler to look at the request and response. It looks fine, both the request and response are well formed JSON:
Raw Request:
{"Bedrooms":"3","BuildingsAD":"Yes","BuildingsMD":"No","BulidingSI":"100000","ContentsAD":"No","ContentsMD":"No","ContentsPOL":"No","ContentsSI":"5000","EffectiveDate":"03/10/2012 23:40:10","EL":"N","MD":"No","NCD":"1","POL":"No","PropType":"Terraced","RiskPostcode":"SW19 1TS","SchemeRef":"20","TA":"No","TenantTheft":"No","TenantType":"Professional","Theft":"No","TransactionDate":"03/10/2012 23:40:10","VolExcess":"250","YearBuilt":"2000 +","ErrorDesc":"123"}
Raw Response:
{"RatingId":"f5733e9d-bc9d-4026-8d5f-ce4f750a3a42","SchemeRef":"20","EffectiveDate":"03/10/2012 23:40:10","TransactionDate":"03/10/2012 23:40:10","Bedrooms":"3","BuildingsAD":"Yes","BuildingsMD":"No","BulidingSI":"100000","ContentsAD":"No","ContentsMD":"No","ContentsPOL":"No","ContentsSI":"5000","EL":"N","MD":"No","NCD":"1","POL":"No","PropType":"Terraced","RiskPostcode":"SW19 1TS","TA":"No","TenantTheft":"No","TenantType":"Professional","Theft":"No","VolExcess":"250","YearBuilt":"2000 +","Error":true,"ErrorDesc":"Rating Sheet not found"}
<script type="text/javascript">
function CalcRating() {
//create a Json object based on data entered by user
var RatingItems = {
AD: $("#AD").val(),
AdminFee: $("#AdminFee").val(),
Bedrooms: $("#Bedrooms").val(),
BuildingsAD: $("#BuildingsAD").val(),
BuildingsMD: $("#BuildingsMD").val(),
BuildingsPremium: $("#BuildingsPremium").val(),
BulidingSI: $("#BulidingSI").val(),
ContentsAD: $("#ContentsAD").val(),
ContentsMD: $("#ContentsMD").val(),
ContentsPOL: $("#ContentsPOL").val(),
ContentsPremium: $("#ContentsPremium").val(),
ContentsSI: $("#ContentsSI").val(),
EffectiveDate: $("#EffectiveDate").val(),
EL: $("#EL").val(),
IPT: $("#IPT").val(),
MD: $("#MD").val(),
NCD: $("#NCD").val(),
POL: $("#POL").val(),
PropType: $("#PropType").val(),
RatingId: $("#RatingId").val(),
RiskPostcode: $("#RiskPostcode").val(),
SchemeRef: $("#SchemeRef").val(),
TA: $("#TA").val(),
TenantTheft: $("#TenantTheft").val(),
TenantType: $("#TenantType").val(),
Theft: $("#Theft").val(),
TransactionDate: $("#TransactionDate").val(),
TotalPremium: $("#TotalPremium").val(),
VolExcess: $("#VolExcess").val(),
YearBuilt: $("#YearBuilt").val(),
ErrorDesc: "123"
};
//call jQuery Ajax method which calls Json.stringify method to convert
//the Json object into string and send it with post method
$.ajax({
url: "/api/qsletpropertyom",
data: JSON.stringify(RatingItems),
type: "POST",
contentType: "application/json;charset=utf-8",
statusCode: {
201: function (result) {
alert("Total Premium: " + result.TotalPremium + ", Total Buildings Premium " + result.BuildingsPremium + ", Total Contents Cover " + result.ContentsPremium + ", Admin Fee " + result.AdminFee);
},
404: function (result1) {
alert(result.ErrorDesc);
},
500: function (result2) {
alert("Unknown Error");
}
}
});
}
Please let me know the error of my ways!!
First of all, you're using result.ErrorDesc when you were probably expecting result1.ErrorDesc - but that's just a typo I guess.
Second of all, if I get you right, you want to display error description to the user when ajax hits 404 (page not found)? If so, most likely you won't be able to do that since there is no data passed to your 404 handler.
Perhaps you're looking for something else like error option for ajax (http://api.jquery.com/jQuery.ajax/).
From jQuery documentation: error "A function to be called if the request fails. The function receives three arguments: The jqXHR (in jQuery 1.4.x, XMLHttpRequest) object, a string describing the type of error that occurred and an optional exception object, if one occurred. Possible values for the second argument (besides null) are "timeout", "error", "abort", and "parsererror". When an HTTP error occurs, errorThrown receives the textual portion of the HTTP status, such as "Not Found" or "Internal Server Error." As of jQuery 1.5, the error setting can accept an array of functions. Each function will be called in turn. Note: This handler is not called for cross-domain script and JSONP requests."
$.ajax({
url: "/api/qsletpropertyom",
data: JSON.stringify(RatingItems),
type: "POST",
contentType: "application/json;charset=utf-8",
error: function(jqXHR, textStatus, errorThrown) {
// textStatus will contain "Not Found" for 404 errors
}
});
EDIT:
Apparently, the 404 handler used in statusCode map definition (as you did) gets 3 arguments, just as error option does. Here's working example: http://jsfiddle.net/QsHdV/2/
Note that first argument you get there is jquery XHR object not some result data.
I think the issue is that you are expecting to get the response text as the first argument in the 404 case, which is not what jQuery returns.
Here some info taken from the jQuery docs :
statusCode(added 1.5)Map
If the request is successful, the status code functions take the same parameters as the success callback; if it results in an error, they take the same parameters as the error callback.
error(jqXHR, textStatus, errorThrown) Function
A function to be called if the request fails. The function receives three arguments: The jqXHR (in jQuery 1.4.x, XMLHttpRequest) object, a string describing the type of error that occurred and an optional exception object, if one occurred. Possible values for the second argument (besides null) are "timeout", "error", "abort", and "parsererror". When an HTTP error occurs, errorThrown receives the textual portion of the HTTP status, such as "Not Found" or "Internal Server Error." As of jQuery 1.5, the error setting can accept an array of functions. Each function will be called in turn. Note: This handler is not called for cross-domain script and JSONP requests. This is an Ajax Event.
success(data, textStatus, jqXHR)Function, Array
A function to be called if the request succeeds. The function gets passed three arguments: The data returned from the server, formatted according to the dataType parameter; a string describing the status; and the jqXHR (in jQuery 1.4.x, XMLHttpRequest) object. As of jQuery 1.5, the success setting can accept an array of functions. Each function will be called in turn. This is an Ajax Event.
As you can see, you aren't given a response data object as an argument when an HTTP error occurs.

Ajax don't receives onError Message

In my aspx login script I don't get server Error messages via Javascript. I don't understand where the problem is or what's wrong.
The script sends an Ajax Response to this URL: login.aspx?ajax=true On error it receives a 403 Error Code with Error message. But the Error message could not been found in the data value. Are there some other parameters in VB that I have to send? Or have I made a mistake in the Javascript?
In Firebug I can see the Error message.
HTML
Login Fail. 3 tries left.
login.aspx
function onError(data) {
$('#errormessage').text(this);
$.mobile.changePage("#loginError", {
transition: "pop",
reverse: false,
changeHash: false
});
$("#Submit1").click(function() {
var formData = $("#loginform").serialize();
$.ajax({
type: "POST",
url: "login.aspx",
cache: false,
data: formData,
success: onSuccess,
error: onError
});
return false;
});
aspx.vb
Catch ex As AccessDeniedException
Response.StatusCode = 403
Response.Write(ex.Message)
'Response.AppendHeader("XML", "<xml><error>" + ex.Message + "</error></xml>")
'Response.StatusDescription = "<xml><error>" + ex.Message + "</error></xml>"
'Response.Status = ex.Message
Response.End()
From jQuery ajax documentation
error(jqXHR, textStatus, errorThrown)Function
A function to be called if the request fails. The function receives three arguments: The jqXHR (in jQuery 1.4.x, XMLHttpRequest) object, a string describing the type of error that occurred and an optional exception object, if one occurred. Possible values for the second argument (besides null) are "timeout", "error", "abort", and "parsererror". When an HTTP error occurs, errorThrown receives the textual portion of the HTTP status, such as "Not Found" or "Internal Server Error." As of jQuery 1.5, the error setting can accept an array of functions. Each function will be called in turn. Note: This handler is not called for cross-domain script and JSONP requests. This is an Ajax Event.
So if you want the HTTP status, put the errorThrown into the html, or dig it out of the jqXHR variable which you data variable currently represents.

Categories

Resources