Domanda

Per aggiungere un po 'di gestione degli errori di base, volevo riscrivere un pezzo di codice che usasse $ .getJSON di jQuery per estrarre alcune foto da Flickr. La ragione di ciò è che $ .getJSON non fornisce la gestione degli errori o non funziona con i timeout.

Poiché $ .getJSON è solo un wrapper per $ .ajax, ho deciso di riscrivere la cosa e sorprendere a sorpresa, funziona perfettamente.

Ora però inizia il divertimento. Quando causo deliberatamente un 404 (modificando l'URL) o causando il timeout della rete (non essendo collegato agli interwebs), l'evento di errore non si attiva affatto. Sono in perdita su ciò che sto facendo di sbagliato. L'aiuto è molto apprezzato.

Ecco il codice:

$(document).ready(function(){

    // var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne"; // correct URL
    var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne_______"; // this should throw a 404

    $.ajax({
        url: jsonFeed,
        data: { "lang" : "en-us",
                "format" : "json",
                "tags" : "sunset"
        },
        dataType: "jsonp",
        jsonp: "jsoncallback",
        timeout: 5000,
        success: function(data, status){
            $.each(data.items, function(i,item){
                $("<img>").attr("src", (item.media.m).replace("_m.","_s."))
                          .attr("alt", item.title)
                          .appendTo("ul#flickr")
                          .wrap("<li><a href=\"" + item.link + "\"></a></li>");
                if (i == 9) return false;
            });
        },
        error: function(XHR, textStatus, errorThrown){
            alert("ERREUR: " + textStatus);
            alert("ERREUR: " + errorThrown);
        }
    });

});

Vorrei aggiungere che questa domanda è stata posta quando jQuery era alla versione 1.4.2

È stato utile?

Soluzione

jQuery 1.5 e versioni successive offrono un supporto migliore per la gestione degli errori con le richieste JSONP. Tuttavia, è necessario utilizzare il metodo $ .ajax anziché $ .getJSON . Per me funziona:

var req = $.ajax({
    url : url,
    dataType : "jsonp",
    timeout : 10000
});

req.success(function() {
    console.log('Yes! Success!');
});

req.error(function() {
    console.log('Oh noes!');
});

Il timeout sembra fare il trucco e chiamare il gestore degli errori, quando non ci sono richieste riuscite dopo 10 secondi.

Ho fatto un po ' blogpost anche su questo argomento.

Altri suggerimenti

Questa è una limitazione nota con l'implementazione jsonp nativa in jQuery. Il testo seguente è tratto da IBM DeveloperWorks

  

JSONP è una tecnica molto potente per   costruire mashup, ma, sfortunatamente,   non è una cura per tutti   esigenze di comunicazione tra domini. esso   presenta alcuni inconvenienti da prendere   in seria considerazione prima   impegnare risorse per lo sviluppo.   Innanzitutto, non vi sono errori   gestione per chiamate JSONP. Se la   l'inserimento dinamico degli script funziona   essere chiamato; in caso contrario, non succede nulla.   Fallisce in silenzio. Per esempio,   non riesci a rilevare un errore 404   dal server. Né puoi annullare o   riavvia la richiesta. Puoi, tuttavia,   timeout dopo aver atteso un ragionevole   quantità di tempo. (Future jQuery   le versioni possono avere una funzione di interruzione per   Richieste JSONP.)

Tuttavia è disponibile un plug-in jsonp su GoogleCode che fornisce supporto per errori la manipolazione. Per iniziare, apporta le seguenti modifiche al codice.

Puoi scaricarlo o semplicemente aggiungere un riferimento di script al plug-in.

<script type="text/javascript" 
     src="http://jquery-jsonp.googlecode.com/files/jquery.jsonp-1.0.4.min.js">
</script>

Quindi modifica la tua chiamata Ajax come mostrato di seguito:

$(function(){
    //var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne"; // correct URL
    var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne_______"; // this should throw a 404  
    $.jsonp({
        url: jsonFeed,
        data: { "lang" : "en-us",
                "format" : "json",
                "tags" : "sunset"
        },
        dataType: "jsonp",
        callbackParameter: "jsoncallback",
        timeout: 5000,
        success: function(data, status){
            $.each(data.items, function(i,item){
                $("<img>").attr("src", (item.media.m).replace("_m.","_s."))
                          .attr("alt", item.title)
                          .appendTo("ul#flickr")
                          .wrap("<li><a href=\"" + item.link + "\"></a></li>");
                if (i == 9) return false;
            });
        },
        error: function(XHR, textStatus, errorThrown){
            alert("ERREUR: " + textStatus);
            alert("ERREUR: " + errorThrown);
        }
    });
});

Una soluzione se sei bloccato con jQuery 1.4:

var timeout = 10000;
var id = setTimeout( errorCallback, timeout );
$.ajax({
    dataType: 'jsonp',
    success: function() {
        clearTimeout(id);
        ...
    }
});

Questo può essere un "noto" limitazione di jQuery; tuttavia, non sembra essere ben documentato. Ho trascorso circa 4 ore oggi cercando di capire perché il mio timeout non funzionava.

Sono passato a jquery.jsonp e ha funzionato come un fascino. Grazie.

Sembra essere risolto a partire da jQuery 1.5. Ho provato il codice sopra e ottengo il callback.

Dico che " sembra essere " perché la documentazione del callback dell'errore per jQuery.ajax () contiene ancora la seguente nota:

  

Nota: questo gestore non viene chiamato per le richieste di script e domini tra domini.

Il plug-in jQuery jquery-jsonp menzionato in Jose Basilio's risposta ora è disponibile su GitHub .

Purtroppo la documentazione è in qualche modo spartana, quindi ho fornito un semplice esempio:

    $.jsonp({
        cache: false,
        url: "url",
        callbackParameter: "callback",
        data: { "key" : "value" },
        success: function (json, textStatus, xOptions) {
            // handle success - textStatus is "success"   
        },
        error: function (xOptions, textStatus) {
            // handle failure - textStatus is either "error" or "timeout"
        }
    });

Importante Includi callbackParameter nella chiamata $ .jsonp (), altrimenti ho scoperto che la funzione di callback non viene mai iniettata nella stringa di query della chiamata di servizio (attuale dalla versione 2.4.0 di jquery-jsonp).

So che questa domanda è vecchia, ma il problema della gestione degli errori con JSONP non è ancora "risolto". Speriamo che questo aggiornamento possa aiutare gli altri in quanto questa domanda è la più votata in Google per la gestione degli errori "jquery jsonp".

Che dire dell'ascolto dell'evento onerror della sceneggiatura? Ho avuto questo problema e l'ho risolto rattoppando il metodo di jquery in cui è stato creato il tag script. Ecco l'interessante codice:

// Attach handlers for all browsers
script.onload = script.onreadystatechange = function( _, isAbort ) {

    if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {

        cleanup();

        // Callback if not abort
        if ( !isAbort ) {
            callback( 200, "success" );
        }
    }
};

/* ajax patch : */
script.onerror = function(){
    cleanup();

    // Sends an inappropriate error, still better than nothing
    callback(404, "not found");
};

function cleanup(){
    // Handle memory leak in IE
    script.onload = script.onreadystatechange = null;

    // Remove the script
    if ( head && script.parentNode ) {
        head.removeChild( script );
    }

    // Dereference the script
    script = undefined;
}

Cosa ne pensi di questa soluzione? È probabile che causi problemi di compatibilità?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top