jQuery jsonp catch "Failed to load resources…" - javascript

I have a Javascript function where I get data via JSONP from my server. I have tried to simulate server errors or lack of internet access (it is supposed to run in a cordova app, so it's possible the client doesn't have internet access), but I can't catch the error. Here is my code:
var completed = false;
jQuery.ajax({
url: "http://www.someDomainThatDoesn'tWork.com/getsContent.php?callback=?",
dataType: "json",
success: function(data) {
completed = true
console.log(data);
},
error: function() {
console.log("fail");
},
statusCode: {
404: function() {
console.log("fail 2");
}
}
}).fail(function() {
console.log("fail 3");
}).always(function() {
if (!completed) {
console.log("fail 4");
}
});
As you can see I try to catch (different) errors in four places. However, if I for example edit the url to one that doesn't exist, the javascript just aborts and give me the error
Failed to load resource: the server responded with a status of 404 (Not Found)
and none of the error catchers gets executed.
In the documentation for jQuery.ajax() it says
Note: This handler is not called for cross-domain script and cross-domain JSONP requests.
so I guess I shouldn't be surprised.
Is there any way to catch this error? I have also tried to embrace it with
try{} catch(error) {}
but that doesn't do the trick either.

Because the JSONP method returns a script it likely fails silently, you may need to change your server to use CORS and not use JSONP in order to be able to get proper error handling.

Related

.fail() fails to execute when ajax request is not successful [duplicate]

Is it possible to catch an error when using JSONP with jQuery? I've tried both the $.getJSON and $.ajax methods but neither will catch the 404 error I'm testing. Here is what I've tried (keep in mind that these all work successfully, but I want to handle the case when it fails):
jQuery.ajax({
type: "GET",
url: handlerURL,
dataType: "jsonp",
success: function(results){
alert("Success!");
},
error: function(XMLHttpRequest, textStatus, errorThrown){
alert("Error");
}
});
And also:
jQuery.getJSON(handlerURL + "&callback=?",
function(jsonResult){
alert("Success!");
});
I've also tried adding the $.ajaxError but that didn't work either:
jQuery(document).ajaxError(function(event, request, settings){
alert("Error");
});
Here's my extensive answer to a similar question.
Here's the code:
jQuery.getJSON(handlerURL + "&callback=?",
function(jsonResult){
alert("Success!");
})
.done(function() { alert('getJSON request succeeded!'); })
.fail(function(jqXHR, textStatus, errorThrown) { alert('getJSON request failed! ' + textStatus); })
.always(function() { alert('getJSON request ended!'); });
It seems that JSONP requests that don't return a successful result never trigger any event, success or failure, and for better or worse that's apparently by design.
After searching their bug tracker, there's a patch which may be a possible solution using a timeout callback. See bug report #3442. If you can't capture the error, you can at least timeout after waiting a reasonable amount of time for success.
Detecting JSONP problems
If you don't want to download a dependency, you can detect the error state yourself. It's easy.
You will only be able to detect JSONP errors by using some sort of timeout. If there's no valid response in a certain time, then assume an error. The error could be basically anything, though.
Here's a simple way to go about checking for errors. Just use a success flag:
var success = false;
$.getJSON(url, function(json) {
success = true;
// ... whatever else your callback needs to do ...
});
// Set a 5-second (or however long you want) timeout to check for errors
setTimeout(function() {
if (!success)
{
// Handle error accordingly
alert("Houston, we have a problem.");
}
}, 5000);
As thedawnrider mentioned in comments, you could also use clearTimeout instead:
var errorTimeout = setTimeout(function() {
if (!success)
{
// Handle error accordingly
alert("Houston, we have a problem.");
}
}, 5000);
$.getJSON(url, function(json) {
clearTimeout(errorTimeout);
// ... whatever else your callback needs to do ...
});
Why? Read on...
Here's how JSONP works in a nutshell:
JSONP doesn't use XMLHttpRequest like regular AJAX requests. Instead, it injects a <script> tag into the page, where the "src" attribute is the URL of the request. The content of the response is wrapped in a Javascript function which is then executed when downloaded.
For example.
JSONP request: https://api.site.com/endpoint?this=that&callback=myFunc
Javascript will inject this script tag into the DOM:
<script src="https://api.site.com/endpoint?this=that&callback=myFunc"></script>
What happens when a <script> tag is added to the DOM? Obviously, it gets executed.
So suppose the response to this query yielded a JSON result like:
{"answer":42}
To the browser, that's the same thing as a script's source, so it gets executed. But what happens when you execute this:
<script>{"answer":42}</script>
Well, nothing. It's just an object. It doesn't get stored, saved, and nothing happens.
This is why JSONP requests wrap their results in a function. The server, which must support JSONP serialization, sees the callback parameter you specified, and returns this instead:
myFunc({"answer":42})
Then this gets executed instead:
<script>myFunc({"answer":42})</script>
... which is much more useful. Somewhere in your code is, in this case, a global function called myFunc:
myFunc(data)
{
alert("The answer to life, the universe, and everything is: " + data.answer);
}
That's it. That's the "magic" of JSONP. Then to build in a timeout check is very simple, like shown above. Make the request and immediately after, start a timeout. After X seconds, if your flag still hasn't been set, then the request timed out.
I know this question is a little old but I didn't see an answer that gives a simple solution to the problem so I figured I would share my 'simple' solution.
$.getJSON("example.json", function() {
console.log( "success" );
}).fail(function() {
console.log( "error" );
});
We can simply use the .fail() callback to check to see if an error occurred.
Hope this helps :)
If you collaborate with the provider, you could send another query string parameter being the function to callback when there's an error.
?callback=?&error=?
This is called JSONPE but it's not at all a defacto standard.
The provider then passes information to the error function to help you diagnose.
Doesn't help with comm errors though - jQuery would have to be updated to also callback the error function on timeout, as in Adam Bellaire's answer.
Seems like this is working now:
jQuery(document).ajaxError(function(event, request, settings){
alert("Error");
});
I use this to catch an JSON error
try {
$.getJSON(ajaxURL,callback).ajaxError();
} catch(err) {
alert("wow");
alert("Error : "+ err);
}
Edit: Alternatively you can get the error message also. This will let you know what the error is exactly. Try following syntax in catch block
alert("Error : " + err);
Mayby this works?
.complete(function(response, status) {
if (response.status == "404")
alert("404 Error");
else{
//Do something
}
if(status == "error")
alert("Error");
else{
//Do something
}
});
I dont know whenever the status goes in "error" mode. But i tested it with 404 and it responded
you ca explicitly handle any error number by adding this attribute in the ajax request:
statusCode: {
404: function() {
alert("page not found");
}
}
so, your code should be like this:
jQuery.ajax({
type: "GET",
statusCode: {
404: function() {
alert("page not found");
}
},
url: handlerURL,
dataType: "jsonp",
success: function(results){
alert("Success!");
},
error: function(XMLHttpRequest, textStatus, errorThrown){
alert("Error");
}
});
hope this helps you :)
I also posted this answer in stackoverflow - Error handling in getJSON calls
I know it's been a while since someone answerd here and the poster probably already got his answer either from here or from somewhere else. I do however think that this post will help anyone looking for a way to keep track of errors and timeouts while doing getJSON requests. Therefore below my answer to the question
The getJSON structure is as follows (found on http://api.jqueri.com):
$(selector).getJSON(url,data,success(data,status,xhr))
most people implement that using
$.getJSON(url, datatosend, function(data){
//do something with the data
});
where they use the url var to provide a link to the JSON data, the datatosend as a place to add the "?callback=?" and other variables that have to be send to get the correct JSON data returned, and the success funcion as a function for processing the data.
You can however add the status and xhr variables in your success function. The status variable contains one of the following strings : "success", "notmodified", "error", "timeout", or "parsererror", and the xhr variable contains the returned XMLHttpRequest object
(found on w3schools)
$.getJSON(url, datatosend, function(data, status, xhr){
if (status == "success"){
//do something with the data
}else if (status == "timeout"){
alert("Something is wrong with the connection");
}else if (status == "error" || status == "parsererror" ){
alert("An error occured");
}else{
alert("datatosend did not change");
}
});
This way it is easy to keep track of timeouts and errors without having to implement a custom timeout tracker that is started once a request is done.
Hope this helps someone still looking for an answer to this question.

What HTTP response codes does the jQuery aJax error handler consider an 'error'?

I have a standard aJax call back to the server:
$.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json',
url: '/Apps/ResetDateAndCount',
data: JSON.stringify({
appName: app
}),
success: function (response) {
$('.lastReset').text(response);
$('.currentCount').text('0');
},
error: function (xhr, status, error) {
alert("You are not authorized to perform that action");
}
});
From my server (ASP.NET) I am returning errors like:
return Json(new { success = false, error = "You are not authorized to perform that action" });
and
Response.StatusCode = 401; return Json(new { success = false, error = "You are not authorized to perform that action" });
and
Response.StatusCode = 500; return Json(new { success = false, error = "You are not authorized to perform that action" });
Inside of the error handler error: function (xhr, status, error) only the last return will be caught as an error, when the status code is set to 500.
I am wondering what response codes aJax actually consider an "error"?
Any error code that is outside of the interval [200, 299] and different than 304 is considered an error by jQuery when making an AJAX call.
Now of course you're gonna ask me, that's fine and dandy but why the hell this is not considered as an error, after all I am returning 401 which outside of the aforementioned interval so it should be considered an error:
Response.StatusCode = 401;
return Json(new { success = false, error = "You are not authorized to perform that action" });
Very simple: because when you return a 401 status code from a controller action in ASP.NET MVC, the framework (and more specifically the ASP.NET Forms Authentication module) will intercept this request and redirect you to the login form eventually resulting in a 200 status code. Yeah, the login page is served with a 200 OK status code. In this case 200 is inside the interval so no error callback is invoked. You can validate this by inspecting the DOM of the login page returned in your success callback for this particular case.
Now put yourself into the perspective of a browser making an AJAX request: It will follow all the redirects that a server makes until it reaches the final destination. If this final destination status code is outside of the interval and different than 304 then you will get the error callback invoked. OK, now things start to make a little more sense.
So the next question you're gonna ask me is how do I invoke the error callback if I return a 401 status code from my controller action, right? Then I will redirect you (:-)) to the following blog post: Prevent Forms Authentication Login Page Redirect When You Don't Want It.
I would suggest checking the list of standard HTTP codes. Please see it here https://en.wikipedia.org/wiki/List_of_HTTP_status_codes. It's self-explanatory.
In other words, any codes >= 400 (4xx, 5xx) can be considered as an error.
You are returning the error message:
"You are not authorized to perform that action"
I'd say, this text message corresponds mostly to 401/403 codes. For 5xx errors, I would suggest you display some server error message.

Error handling cross domain jquery ajax call

I am performing one cross domain get operation as shown below.
$.ajax({
type: "GET",
url: "http://localhost:65249/api/item/get",
data: {
searchText: "test"
},
dataType: "jsonp",
async: false,
success: function (results) {
alert(results);
},
error: function (jqXHR, error, errorThrown) {
if (jqXHR.status && jqXHR.status == 401) {
alert("Unauthorized request");
} else if (jqXHR.status && jqXHR.status == 404) {
alert("The requested page not found");
}
}
});
But success or error block is not getting called after request is completed. when i debug java script in developer console i am receiving error but error block of javascript is not getting called.
GET http://localhost:65249/api/item/getallproducts?callback=jQuery182028460139059461653_1396510235829&searchText=test&_=1396510674779 401 (Unauthorized)
Unfortunately, if you are using JSONP, all requests that return an error fail silently. This is because JSONP uses a script tag instead of XmlHttpRequest. If you want errors to fire, you need to use XHR with CORS. CORS needs to be configured on the server side, and it works client side only in IE 10+.
error dont work on corss domain calls, see jquery doku. for error:
Note: This handler is not called for cross-domain script and
cross-domain JSONP requests.
Take a look at this answer:
JSONP request error handling

Error handling and saving logs to text files

I want to do error handling in javascript.
I want to log the error occurred in the javascript.
I don't want to use the database to store the errors.I want to store all the error in a txt file(that txt file should be present in the server where that website is hosted. So that others can't access that file.
How to do the above requirement.
I searched in Google and find
function WriteToFile() {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var s = fso.CreateTextFile("C:\\Test.txt", true);
s.WriteLine('Hello');
s.Close();
}
this is also not working in all conditions.
1. You're using a non-ie browser (which doesn't support activex objects)
2. you're using an ie browser on an xp machine with sp2 installed and the activex object is being blocked
So please help me to solve this problem.
Thanks in advance.
Use a try/catch to detect the error first of all:
try
{
// code that could error here
}
catch(err)
{
// do an ajax call to the server
}
In the catch block, you could do an ajax call to the server. On the server you will need some server side script (such as PHP, ASP etc etc) to process the request and log the error to a local text file. In the catch block above, err.message will give you the error message string which you can include in your ajax call.
HI you can use alternative way to handle the error as below code
jQuery.ajax({
type: "POST",
url: "urlpage",
dataType: "html",
data: "types":$("#catid").val(),
success: function (response) {
alert("Successfully!!!");
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});
When any error occurred you can call another ajax function or same function once again.
This works mostly in all ajax call to handle error, Try it.

jQuery ajax - Absolute URL's and error handling

Is it possible to catch the HTTP errors (like 404, 500, 504 etc) when we call an external webservice by specifying an absolute url?. (like setting the url: attribute of $.ajax call to have a url value as http://api.geonames.org/findNearbyPostalCodes.
Right now I'm unable to receive any errors although firebug is catching them and showing it in the console.
Can someone help?
Here is my code.
$.ajax({
type: 'GET',
url: "http://api.geonames.org/findNearbyPostalCodes",
data: '{"lat":47,"lng":"9","username":"demo"}',
dataType: 'json',
cache:false,
async:false,
statusCode:{
404: function(){
alert('Page not found');
},
500: function(){
alert('Page not found');
},
504: function(){
alert('Unknown host');
}
},
success: function(data){
alert(data);
}
error: function (xhr, exception, thrownError)
{
alert(xhr.status);
}
});
No, it is not possible with cross-domain (external) requests using only client-side code. This is because cross-domain requests rely on JSONP - ie, injecting a script tag that loads code from an external source. Unfortunately, the <script> element does not have anything like an onerror event.
You can handle errors with same-domain requests because these typically use XMLHttpRequest, which returns a lot of useful information like status codes and response headers.
Your best bet would be to use your local server as a proxy.
If using an absolute URL causes the domain to be different from the domain of your page (cross-domain request), then the only way to successfully execute an ajax call is to use JSONP which will cause the ajax library to use <script> tags for the cross-domain request instead of the more typical XMLHttpRequest used for same-domain requests.
You will not be able to intercept any sort of status codes from the loading of the cross-domain <script> tag.
In your case, you cannot check the status code (assuming you're not making the request from api.geonames.org).
jQuery will always return a "0" as the status if the request is cross-domain:
$.ajax({
type: 'GET',
url: 'http://someotherdomain.com/api/query',
dataType: 'json',
data: '{"first": 1, "second": 2}',
complete: function(response) { // the 'response' object has the status code
if (response.status == '200') {
// do something on success
} else if (response.status == '0') {
alert('Your request is cross-domain');
}
}
});
If the request happens to be within the same domain, you'll get a valid status code that you can check (the complete attribute of the $.ajax() function will run after any success or failure callbacks are run).

Categories

Resources