Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make jQuery parse my error response represented as a valid json?

Tags:

jquery

ajax

Here is my code:

      $.ajax({
        url: "/api/invoice/" + newInvoice._id,
        type: 'PUT',
        data: JSON.stringify(newInvoice),
        dataType: 'json',
        contentType: "application/json; charset=utf-8"
      })
        .success(function () {
          $('#statusLine').text('Successfully submitted invoice {0}. Click here to dismiss.'.format(newInvoice._id));
        })
        .error(function (err) {
          alert(err);
        });

The request:

PUT http://localhost:8000/api/invoice/16211 HTTP/1.1
Host: localhost:8000
Connection: keep-alive
Content-Length: 770
Origin: http://localhost:8000
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11
Content-Type: application/json; charset=UTF-8
Accept: application/json, text/javascript, */*; q=0.01
Referer: http://localhost:8000/invoice.html?id=16211
Accept-Encoding: gzip,deflate,sdch
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

{"items":[{"id":...

The request body is actually a valid json, I have just truncated it for brevity.

The response:

HTTP/1.1 409 Conflict
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 1386
ETag: 250542419
Connection: keep-alive

{
  "msg": "Cannot update the invoice #16211, because it has already been updated by someone else.",
  "invoice": {
    "items": [
      {...

Again, the response is a completely valid json, truncated for brevity.

As expected, the error handler is invoked with the err object. However, how can I get hold on the parsed json? Of course, I could check that the content-type of the response is json and then parse the err.responseText myself, but isn't it what jQuery ajax is supposed to do for me? I mean, it does so for my $.get queries when I get the objects from the server.

What am I missing?

EDIT

This is a correction to https://stackoverflow.com/a/12310751/80002:

Doing the request:

var ajax = $.ajax(...

Processing the error response:

var res, ct = ajax.getResponseHeader("content-type") || '';
if (ct.indexOf('json') > -1) {
  res = $.parseJSON(err.responseText);
  // process the response here
}
like image 514
mark Avatar asked Sep 07 '12 01:09

mark


3 Answers

I ran into the same issue and found a slightly different way from @Barmar's answer.

Aswell as responseText, there is also a responseJSON property, so you could do the following:

var json_response = err.responseJSON.msg;

If you console.log(err); there's a few properties in there that you might wish to use in your error message on the page.

like image 131
martincarlin87 Avatar answered Nov 19 '22 07:11

martincarlin87


For an error message with a non-2001HTTP status code, the content will not be parsed by jQuery. If you'd really like not to parse the returned result to JSON yourself, you would have to return a HTTP status 200 and use the success (done) callbacks.

It's a good sign that you're using (from your example) HTTP code 409, and I think you should keep doing that - just bite the bullet and parse the JSON manually in your error handler. If the parsing fails, something else has gone wrong (like a temporary network failure), but this will allow you to build a nice API that you (and possibly others) can consume without having to build too much error checking into the success function.

Keep success for the happy results, and error for unhappy results.

1 Technically any 2xx status should be considered successful; in jQuery (status >= 200 && status < 300 || status === 304) counts as something successful.

like image 25
Joel Purra Avatar answered Nov 19 '22 08:11

Joel Purra


Call $.parseJSON explicitly in your error callback:

(...)
.error(function (err) {
  var msg = $.parseJSON(err).msg;
  alert(msg);
});
like image 12
Barmar Avatar answered Nov 19 '22 07:11

Barmar