Related
I'm making an ajax jsonp request, but the failure error handling wont work. If the request is 404 or 500 it won't handle the error.
I've been looking around to find an answer to this, but can't find anything. There seems to be a solution with http://code.google.com/p/jquery-jsonp/, but I can't find any examples on how to use it.
function authenticate(user, pass) {
$.ajax ({
type: "POST",
url: "url",
dataType: 'jsonp',
async: false,
//json object to sent to the authentication url
data: {"u": userid, "p": pass},
success: function (data) {
//successful authentication here
console.log(data);
},
error: function(XHR, textStatus, errorThrown) {
alert("error: " + textStatus);
alert("error: " + errorThrown);
}
})
}
If you check jQuery.ajax() documentation, you can find:
error
A function to be called if the request fails (...) Note: This handler is not called for cross-domain script and cross-domain JSONP requests. This is an Ajax Event.
Because of that, you're forced to find workaround. You can specify timeout to trigger an error callback. It means that within specified time frame the request should be successfully completed. Otherwise, assume it has failed:
$.ajax({
...
timeout: 5000, // a lot of time for the request to be successfully completed
...
error: function(x, t, m) {
if(t==="timeout") {
// something went wrong (handle it)
}
}
});
Other issues in your code...
While JSONP (look here and here) can be used to overcome origin policy restriction, you can't POST using JSONP (see CORS instead) because it just doesn't work that way - it creates a element to fetch data, which has to be done via GET request. JSONP solution doesn't use XmlHttpRequest object, so it is not an AJAX request in the standard way of understanding, but the content is still accessed dynamically - no difference for the end user.
$.ajax({
url: url,
type: "GET"
dataType: "jsonp",
...
Second, you provide data incorrectly. You're pushing javascript object (created using object literals) onto the wire instead of its serialized JSON representation. Create JSON string (not manually, use e.g. JSON.stringify converter):
$.ajax({
...
data: JSON.stringify({u: userid, p: pass}),
...
Last issue, you've set async to false, while documentation says:
Cross-domain requests and dataType: "jsonp" requests do not support
synchronous operation.
Two ways to handle error,
There is no error handling for cross domain JSONP requests. Use jsonp plug-in available on Github https://github.com/jaubourg/jquery-jsonp that provides support for error handling.
jQuery ajax Timeout - Timeout after a reasonable amount of time to fire the error callback because it might have failed silently. You may not know what the actual error (or error status) was but at least you get to handle the error
I've been struggling like you for a while trying to handle errors on ajax jsonp DataType requests, however I want to share you my code, hope it helps. A basic thing is to include a timeout on the ajax request, otherwise it'll never enter the error: function
$.ajax({
url: "google.com/api/doesnotexists",
dataType: "jsonp",
timeout: 5000,
success: function (parsed_json) {
console.log(parsed_json);
},
error: function (parsedjson, textStatus, errorThrown) {
console.log("parsedJson: " + JSON.stringify(parsedjson));
$('body').append(
"parsedJson status: " + parsedjson.status + '</br>' +
"errorStatus: " + textStatus + '</br>' +
"errorThrown: " + errorThrown);
}
});
jsfiddle - Handle Errors with jquery ajax call and JSONP dataType - Error 404
I'm building a fragile JS project that uses jquery-jsonp, and came up with a dual-jsonp/ajax approach that handles errors no matter which method ends up being used.
function authenticate(user, pass) {
var ajax = ($.jsonp || $.ajax)({
'url': /* your auth url */,
'data': { /* user, pass, ... */ },
'contentType': "application/javascript",
'dataType': 'jsonp',
'callbackParameter': 'callback' // $.jsonp only; $.ajax uses 'jsonpCallback'
});
ajax.done(function (data) {
// your success events
});
ajax.fail(function (jqXHR, textStatus, errorThrown) {
// $.jsonp calls this func as function (jqXHR, textStatus)
// and $.ajax calls this func with the given signature
console.error('AJAX / JSONP ' + textStatus + ': ' +
(errorThrown || jqXHR.url));
});
}
Since both jquery-jsonp and $.ajax support the jQuery Deferred specification, we can merge the two error handlers together, handling 400 and 500-series errors, as well as lookup timeouts.
Old question but I had the same problem. Here is a solution that worked for me.
If you own the domain you shoot your request at, you can set a variable in the response and check for it on the client side.
Server Side:
SERVER_RESPONSE=true; Callback(parameter1, parameter2);
Client Side:
if(typeof SERVER_RESPONSE === 'undefined'){
console.log('No Response, maybe server is down');
}
else{
console.log('Got a server response');
}
I have a question about ajax success. So in previous situations I have returned Data something like ID but now in this case I'm returning entire table. So I would like to check if Ajax was successful(200 OK) before I retrieve my data. What is the best way to do that? Also I use new way to retrieve data and check for errors with JQuery. Here is example of my code:
<div id="box"></div>
function getSlots(fld){
var userID = '134';
$j.ajax({
type: 'POST',
url: 'AjaxData.html',
cache: false,
data: {'userID':userID},
dataType: "html",
async: false
})
.done(function(html){
$j('#box').html(html);
})
.fail(function(jqXHR, textStatus, errorThrown){
gwLogIt(errorThrown);
});
}
You don't need to check. The various callbacks are called under the following conditions:
.done() or success: are called when the AJAX call is successful.
.fail() or error: are called when there's an error (either from the server or in the jQuery code that parses the response).
.always() or complete: are called in either case.
from official docs:
$.ajax({
statusCode: {
404: function() {
alert( "page not found" );
}
}
});
http://api.jquery.com/jQuery.ajax/
also if you use something like babel to transpile ES6, you can use fetch api for ajax calls. I personally stopped using jQuery ±2 years ago.. when moved to React world :)
I'm having a trouble with ajax requests and server responses:
$.ajax({
url: servurl,
dataType: "jsonp",
data: {... },
crossDomain: true,
error: function(){},
success: function(){},
complete: function(){alert('complete')}
});
}
The thing is - sometimes I get succes, when I should get it, but sometimes I can get 500 status, and it is normal and expected.
The same ajax call works for correct requests, but fails for others.
I want to display an error message if I get a 500 server error, but for some reason the ajax does not complete. Thus, neither error: nor complete: work.
Maybe the reason for that is 'jsonp' datatype? Other datatypes do not work though.
Can someone help please?
Or maybe give me an advice on how to detect server status any other way.
jsonp requests do not trigger error callbacks by design, therefore there is no way for you to catch the error with javascript. I suggest instead implementing an error handler on your server that detects a jsonp request and returns jsonp that indicates an error has occured rather than a 500 status code.
Note that error: is deprecated as of 1.8 and is not called for JSONP however I wonder if you might have success using the Promise functionality introduced with 1.5 for deferred http://api.jquery.com/category/deferred-object/ as:
jqXHR.fail(function(jqXHR, textStatus, errorThrown) {});
jqXHR.done(function(data, textStatus, jqXHR) {});
jqXHR.always(function(data|jqXHR, textStatus, jqXHR|errorThrown) { });
Example for your code:
$.ajax({
url: servurl,
dataType: "jsonp",
data: {... },
crossDomain: true
}).done(function(data, textStatus, jqXHR){ //replace success
alert(textStatus);
}).always(function(data|jqXHR, textStatus, jqXHR|errorThrown) { // replace complete
alert(textStatus);
}).fail(function(jqXHR, textStatus, errorThrown) { // replace error
alert(errorThrown);
});
Make sure that you are accessing to your server. Maybe you are requesting in your server for an specific contentType (like application/json) and you are not using that property into your ajax call.
As you requested, to show any message if get a error (400, 404, 500...), you can use my custom function for ajax error responses:
function onErrorFunc(jqXHR, status, errorText) {
alert('Status code: ' + jqXHR.status + '\nStatus text: ' + status +
'\nError thrown: ' + errorText);
}
Usage:
$.ajax({
//some options
error: onErrorFunc
});
Please, show us what error thrown your server.
Thank you all for comments. Jquery .ajax really does not give errors on jsonp requests.
The way to get error messages was to implement the jquery-jsonp plugin:
https://github.com/jaubourg/jquery-jsonp
A little background:
I am trying to implement and AJAX powered SlickGrid. There isn't much documentation so I used this example as a base.
In this example there is the following code that hits the desired web service to get the data:
req = $.jsonp({
url: url,
callbackParameter: "callback",
cache: true, // Digg doesn't accept the autogenerated cachebuster param
success: onSuccess,
error: function(){
onError(fromPage, toPage)
}
});
req.fromPage = fromPage;
req.toPage = toPage;
I'm not exactly sure what jsonp does but from what i've read it appears to be very similar to the ajax method in jQuery except it returns json and allows cross domain requests. The webservice that I happen to be calling only returns XML so I changed this chunk of code to:
req = $.ajax({
url: "/_vti_bin/lists.asmx",
type: "POST",
dataType: "xml",
data: xmlData,
complete: onSuccess,
error: function (xhr, ajaxOptions, thrownError) {
alert("error: " + xhr.statusText);
alert(thrownError);
},
contentType: "text/xml; charset=\"utf-8\""
});
req.fromPage = fromPage;
req.toPage = toPage;
My issue is that my page errors out at req.fromPage = fromPage; because req is null.
Am I wrong to think that I can just replace my jsonp call with a call to the ajax method? Is req just not set because my ajax call hasn't finished by the time that code is executed? How can I get around either of these issues?
If I comment out the last two lines and hard-code those values elsewhere everything runs fine.
Am I wrong to think that I can just replace my jsonp call with a call to the ajax method?
No, that should work just fine.
Is req just not set because my ajax call hasn't finished by the time that code is executed?
Yes, that is correct.
The ajax methods starts the request and returns immediately. If you want to do something after the response has arrived you should do that in the success event handler.
You might actually want to use the success event instead of the complete event, as the complete event happens even if there is an error.
You could specify async: false, in your settings to make the ajax call wait for the response, but that means that the browser freezes while it's waiting.
As Guffa stated, $.ajax() works asynchronically. Thus, you have to specify a callback that will be called when the request has returned a response, rather than to just use whatever $.ajax() returns.
There are a couple of different callback methods you can specify:
complete - runs when you recieve a response, regardless of its status.
success - runs when you recieve a response with a successful status code (usually 200).
error - runs when you recieve a response with an error code (for example 404 or 500).
To do something with the response body after a successful request, you should do something like
$.ajax({
...
success: function(body) {
alert('This is the method body:' + body);
}
});
Read up in the documentation on the different methods to see what more parameters you can use.
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.