views:

597

answers:

7

I do a bunch of json requests with dynamic script tags. Is it possible to detect if there's an error in the request (eg. 503 error, 404 error) and run something on detection of the error?

+4  A: 

AFAIK, there's no way to access status code of some external asset loaded from the document (such as script, style or image). Even detecting error (via, say, onerror event handler) is not that widely supported across browsers.

If whatever you're loading falls under SOP, use XHR which gives you access to response headers. Otherwise, you can try looking into recently introduced X-domain XHR.

kangax
+9  A: 

use ajax instead. AFAIK there is no way to detect if a script tag loads or not, and if not, why it didn't load. Using ajax you can load the json and it will tell you why it didn't load.

Using a library like jQuery this becomes very simple:

$.ajax({
  type: "GET",
  url: "test.js",
  dataType: "script",
  error: function(xhr, error, exception){
    alert(xhr.status); //Will alert 404 if the script does not exist
  }
});
Marius
But... but... there is a way.
Ates Goral
+1  A: 

http://www.phpied.com/javascript-include-ready-onload/ ?

Kane
This does appear to be the solution. If you were to add some text explaining it and/or include the sample code from the referenced page in the answer, you might get some upvotes and rewarded with the accepted answer.
Mads Hansen
link explains it pretty much, don't want to pollute space with copy/paste increasing entropy lol.
Kane
I don't find this link relevant. The linked article is about detecting successful loading, not error detection.
Eric Bréchemier
A: 

If you want to detect errors, listen for an error event and compare the fileName property of the error with the file name of the script. If they match, you then handle the error. The thing is, I think that the fileName property is Firefox and Opera-only. Most browsers that have a stacktrace for errors can also simulate this behaviour.

Here's an example, as requested by Eric Bréchemier:

var getErrorScriptNode = (function () {
    var getErrorSource = function (error) {
        var loc, replacer = function (stack, matchedLoc) {
            loc = matchedLoc;
        };

        if ("fileName" in error) {
            loc = error.fileName;
        } else if ("stacktrace" in error) { // Opera
            error.stacktrace.replace(/Line \d+ of .+ script (.*)/gm, replacer);
        } else if ("stack" in error) { // WebKit
            error.stack.replace(/at (.*)/gm, replacer);
            loc = loc.replace(/:\d+:\d+$/, "");
        }
        return loc;
    },
    anchor = document.createElement("a");

    return function (error) {
        anchor.href = getErrorSource(error);
        var src = anchor.href,
        scripts = document.getElementsByTagName("script");
        anchor.removeAttribute("href");
        for (var i = 0, l = scripts.length; i < l; i++) {
            anchor.href = scripts.item(i).src;
            if (anchor.href === src) {
                anchor.removeAttribute("href");
                return scripts.item(i);
            }
        }
    };
}());
Eli Grey
how can you do that? any example?
Eric Bréchemier
Eric: I added an example.
Eli Grey
+3  A: 

I'm assuming you want this to work cross-domain, which is why you can't use XHR?

Try creating two script tags for each request, the first does your standard JSONP request, the second is basically an error handler.

If the first script tag executes, then clear the error handler in your callback. But if the first gets a 404, the error handler inside the second script tag will be run.

You probably also want to set a timeout, to cope with a slow JSONP response.

Will Moffat
A: 

If you need to cross domains (and need the page to work portably), you have to use dynamic script tags.

If you have access to the remote server, you can pass back an error code from the server, and have the server page return 200.

Whether you have access or not, you can use setTimeout when you create the script tag, passing a function that will trigger an error if it expires before the jsonp handler is called. Make sure that the jsonp handler aborts if the error handler has been called.

You'll need to track each request through a global collection, but you'll gain the ability to cancel and count requests. This is similar to the way that XHR objects are managed by a library like jQuery.

Lang Martin
A: 

If you're using jQuery, check out jQuery-JSONP which is a jQuery plugin that does a fairly decent job of doing the <script> insertion for you as well as detecting fetch errors.

Quoting from the project page, jQuery-JSONP features:

  • error recovery in case of network failure or ill-formed JSON responses,
  • precise control over callback naming and how it is transmitted in the URL,
  • multiple requests with the same callback name running concurrently,
  • two caching mechanisms (browser-based and page based),
  • the possibility to manually abort the request just like any other AJAX request,
  • a timeout mechanism.
Ates Goral
But there's no way to know actual status code of failed request, is there?
kangax