215

How can you handle errors in a getJSON call? Im trying to reference a cross-domain script service using jsonp, how do you register an error method?

user2314737
  • 27,088
  • 20
  • 102
  • 114
Ajay
  • 7,378
  • 18
  • 57
  • 75
  • Seems to be a duplicate of **[How do I catch jQuery $.getJSON (or $.ajax with datatype set to 'jsonp') error when using JSONP?](http://stackoverflow.com/questions/309953/how-do-i-catch-jquery-getjson-or-ajax-with-datatype-set-to-jsonp-error-w)** – hippietrail Dec 18 '11 at 16:04
  • Ajay, why not considering marking the correct answer? – Ionică Bizău Mar 19 '15 at 12:30
  • @IonicăBizău Marked it now. I just lost track of this for a while. The top answer is not talking about JSONP. As pointed out by Ben Shelock, there is no supported error handler is what I believe.. – Ajay Mar 19 '15 at 21:15

9 Answers9

297

$.getJSON() is a kind of abstraction of a regular AJAX call where you would have to tell that you want a JSON encoded response.

$.ajax({
  url: url,
  dataType: 'json',
  data: data,
  success: callback
});

You can handle errors in two ways: generically (by configuring your AJAX calls before actually calling them) or specifically (with method chain).

'generic' would be something like:

$.ajaxSetup({
      "error":function() { alert("error");  }
});

And the 'specific' way:

$.getJSON("example.json", function() {
  alert("success");
})
.done(function() { alert("second success"); })
.fail(function() { alert("error"); })
.always(function() { alert("complete"); });
Paul Fournel
  • 10,807
  • 9
  • 40
  • 68
Luciano Costa
  • 3,492
  • 2
  • 16
  • 8
  • Nops! You can go as you like there. Take a look at the docs for more detailed help: [http://api.jquery.com/jQuery.ajax](http://api.jquery.com/jQuery.ajax) – Luciano Costa Jun 15 '11 at 12:36
  • 5
    Note that this requires jQuery 1.5+ (was trying to get it working w/ jQuery 1.3 and wondering why it was complaining about invalid method :-) – kenyee Dec 13 '11 at 22:01
  • 24
    The OP is asking specifically about cross-site `JSONP` at it seems `getJSON` in such case doesn't call the `error()` function. I'm having the same problem. I guess it's to do with how `JSONP` is handled totally different to normal `AJAX` calls in `jQuery` despite `getJSON` handling both. `JSON` is done with an `XMLHTTPRequest` object but `JSONP` is done by dynamically adding a ` – hippietrail Dec 18 '11 at 16:01
  • 3
    The jQuery Doc says "Note: This handler is not called for cross-domain script and JSONP requests." http://api.jquery.com/jQuery.ajax/ > error – OneWorld Aug 08 '12 at 17:57
  • You need to add time out to have the error event fire, this solution didn't work for me but this did http://stackoverflow.com/questions/1002367/jquery-ajax-jsonp-ignores-a-timeout-and-doesnt-fire-the-error-event – yoshyosh Aug 26 '13 at 19:26
  • Please note that `sucess`, `error`, and `complete` are deprecated as of jQuery 1.8. Refer to http://stackoverflow.com/a/19075640/6224885 for the most accurate answer. – snow Aug 31 '16 at 21:52
  • 10
    "The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callback methods introduced in jQuery 1.5 are deprecated as of jQuery 1.8. To prepare your code for their eventual removal, use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead." – Skorunka František Oct 16 '16 at 14:42
  • If you get `Uncaught TypeError: $.getJSON(...).error is not a function`, then follow @SkorunkaFrantišek's advice of using `.fail` instead. – Garrett Dec 08 '16 at 03:11
  • Deprecated functionality – DiggyJohn Mar 13 '20 at 14:36
90

Someone give Luciano these points :) I just tested his answer -had a similar question- and worked perfectly...

I even add my 50 cents:

.error(function(jqXHR, textStatus, errorThrown) {
        console.log("error " + textStatus);
        console.log("incoming Text " + jqXHR.responseText);
    })
frenetix
  • 1,199
  • 1
  • 11
  • 19
82

Here's my addition.

From http://www.learnjavascript.co.uk/jq/reference/ajax/getjson.html and the official source

"The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callback methods introduced in jQuery 1.5 are deprecated as of jQuery 1.8. To prepare your code for their eventual removal, use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead."

I did that and here is Luciano's updated code snippet:

$.getJSON("example.json", function() {
  alert("success");
})
.done(function() { alert('getJSON request succeeded!'); })
.fail(function() { alert('getJSON request failed! '); })
.always(function() { alert('getJSON request ended!'); });

And with error description plus showing all json data as a string:

$.getJSON("example.json", function(data) {
  alert(JSON.stringify(data));
})
.done(function() { alert('getJSON request succeeded!'); })
.fail(function(jqXHR, textStatus, errorThrown) { alert('getJSON request failed! ' + textStatus); })
.always(function() { alert('getJSON request ended!'); });

If you don't like alerts, substitute them with console.log

$.getJSON("example.json", function(data) {
  console.log(JSON.stringify(data));
})
.done(function() { console.log('getJSON request succeeded!'); })
.fail(function(jqXHR, textStatus, errorThrown) { console.log('getJSON request failed! ' + textStatus); })
.always(function() { console.log('getJSON request ended!'); });
user2314737
  • 27,088
  • 20
  • 102
  • 114
12

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.

Tom Groentjes
  • 1,053
  • 8
  • 7
  • 2
    This doesn't work. The "success" callback, as its name implies, is only called on success. (So I'm not sure what the "status" parameter is for...) – jwelsh Jun 26 '15 at 18:06
4

$.getJSON("example.json", function() {
  alert("success");
})
.success(function() { alert("second success"); })
.error(function() { alert("error"); })

It is fixed in jQuery 2.x; In jQuery 1.x you will never get an error callback

Pavlo O.
  • 76
  • 1
  • 4
2

Why not

getJSON('get.php',{cmd:"1", typeID:$('#typesSelect')},function(data) {
    // ...
});

function getJSON(url,params,callback) {
    return $.getJSON(url,params,callback)
        .fail(function(jqXMLHttpRequest,textStatus,errorThrown) {
            console.dir(jqXMLHttpRequest);
            alert('Ajax data request failed: "'+textStatus+':'+errorThrown+'" - see javascript console for details.');
        })
}

??

For details on the used .fail() method (jQuery 1.5+), see http://api.jquery.com/jQuery.ajax/#jqXHR

Since the jqXHR is returned by the function, a chaining like

$.when(getJSON(...)).then(function() { ... });

is possible.

phil294
  • 10,038
  • 8
  • 65
  • 98
1

I was faced with this same issue, but rather than creating callbacks for a failed request, I simply returned an error with the json data object.

If possible, this seems like the easiest solution. Here's a sample of the Python code I used. (Using Flask, Flask's jsonify f and SQLAlchemy)

try:
    snip = Snip.query.filter_by(user_id=current_user.get_id(), id=snip_id).first()
    db.session.delete(snip)
    db.session.commit()
    return jsonify(success=True)
except Exception, e:
    logging.debug(e)
    return jsonify(error="Sorry, we couldn't delete that clip.")

Then you can check on Javascript like this;

$.getJSON('/ajax/deleteSnip/' + data_id,
    function(data){
    console.log(data);
    if (data.success === true) {
       console.log("successfully deleted snip");
       $('.snippet[data-id="' + data_id + '"]').slideUp();
    }
    else {
       //only shows if the data object was returned
    }
});
Nick Woodhams
  • 11,977
  • 10
  • 50
  • 52
  • This is fine for errors that occur within the server, but it doesn't capture when the call can not reach the server or if there is an error thrown before it hits the server code, such as if an MVC user is no longer authenticated. – Lee Oades Jan 13 '17 at 14:02
0

In some cases, you may run into a problem of synchronization with this method. I wrote the callback call inside a setTimeout function, and it worked synchronously just fine =)

E.G:

function obterJson(callback) {


    jqxhr = $.getJSON(window.location.href + "js/data.json", function(data) {

    setTimeout(function(){
        callback(data);
    },0);
}
Newd
  • 2,174
  • 2
  • 17
  • 31
0

This is quite an old thread, but it does come up in Google search, so I thought I would add a jQuery 3 answer using promises. This snippet also shows:

  • You no longer need to switch to $.ajax to pass in your bearer token
  • Uses .then() to make sure you can process synchronously any outcome (I was coming across this problem .always() callback firing too soon - although I'm not sure that was 100% true)
  • I'm using .always() to simply show the outcome whether positive or negative
  • In the .always() function I'm updating two targets with the HTTP Status code and message body

The code snippet is:

    $.getJSON({
         url: "https://myurl.com/api",
         headers: { "Authorization": "Bearer " + user.access_token}
    }).then().always(   function (data, textStatus) {
        $("#txtAPIStatus").html(data.status);
        $("#txtAPIValue").html(data.responseText);
    });
From Orbonia
  • 616
  • 5
  • 16