Pregunta

Para agregar un manejo básico de errores, quise reescribir un fragmento de código que usó $ .getJSON de jQuery para obtener algunas fotos de Flickr. La razón para hacer esto es que $ .getJSON no proporciona manejo de errores ni trabaja con tiempos de espera.

Ya que $ .getJSON es solo un envoltorio alrededor de $ .ajax, decidí reescribirlo y, por sorpresa, funciona perfectamente.

Ahora la diversión comienza sin embargo. Cuando causo deliberadamente un 404 (cambiando la URL) o causo que la red se agote (al no estar conectado a las redes), el evento de error no se dispara, en absoluto. Estoy en una pérdida en cuanto a lo que estoy haciendo mal. La ayuda es muy apreciada.

Aquí está el código:

$(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);
        }
    });

});

Me gustaría agregar que esta pregunta se hizo cuando jQuery estaba en la versión 1.4.2

¿Fue útil?

Solución

jQuery 1.5 y superior tienen mejor soporte para el manejo de errores con solicitudes JSONP. Sin embargo, debe utilizar el método $ .ajax en lugar de $ .getJSON . Para mí, esto funciona:

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

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

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

El tiempo de espera parece hacer el truco y llamar al controlador de errores, cuando no hay una solicitud exitosa después de 10 segundos.

Hice un poco blogpost sobre este tema también.

Otros consejos

Esta es una limitación conocida con la implementación nativa de jsonp en jQuery. El texto a continuación es de IBM DeveloperWorks

  

JSONP es una técnica muy poderosa para   construyendo mashups, pero, desafortunadamente,   no es una cura para todos sus   necesidades de comunicación entre dominios. Eso   tiene algunos inconvenientes que deben ser tomados   en seria consideración antes   comprometiendo recursos de desarrollo.   En primer lugar, no hay error   manejo de llamadas JSONP. Si el   la inserción dinámica de guiones funciona, tu   ser llamado Si no, no pasa nada.   Simplemente falla en silencio. Por ejemplo,   no eres capaz de atrapar un error 404   desde el servidor. Tampoco puedes cancelar o   reiniciar la solicitud. Usted puede, sin embargo,   tiempo de espera después de esperar un razonable   cantidad de tiempo. (Futuro jQuery   versiones pueden tener una función de cancelación para   Solicitudes JSONP.)

Sin embargo, hay un complemento jsonp disponible en GoogleCode que brinda soporte para errores manejo. Para comenzar, simplemente realice los siguientes cambios en su código.

Puede descargarlo o simplemente agregar una referencia de script al complemento.

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

Luego modifique su llamada ajax como se muestra a continuación:

$(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 solución si estás atascado con jQuery 1.4:

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

Esto puede ser un " conocido " limitación de jQuery; sin embargo, no parece estar bien documentado. Hoy pasé unas 4 horas tratando de entender por qué mi tiempo de espera no estaba funcionando.

Cambié a jquery.jsonp y funcionó como un encanto. Gracias.

Parece estar resuelto a partir de jQuery 1.5. He probado el código de arriba y recibo la devolución de llamada.

Lo que digo "parece ser" porque la documentación de la devolución de llamada de error para jQuery.ajax () aún tiene la siguiente nota:

  

Nota: este controlador no se llama para secuencias de comandos de dominio cruzado y solicitudes JSONP.

El complemento jQuery jquery-jsonp mencionado en Jose Basilio's respuesta ahora se puede encontrar en GitHub .

Desafortunadamente, la documentación es un tanto espartana, por lo que proporcioné un ejemplo simple:

    $.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 Incluya el parámetro de devolución de llamada en la llamada $ .jsonp (), de lo contrario, descubrí que la función de devolución de llamada nunca se inyecta en la cadena de consulta de la llamada de servicio (vigente a partir de la versión 2.4.0 de jquery-jsonp).

Sé que esta pregunta es antigua, pero el problema del manejo de errores con JSONP aún no está "resuelto". Esperamos que esta actualización ayude a otros ya que esta pregunta es la mejor clasificada dentro de Google para el manejo de errores " jquery jsonp " ;.

¿Qué hay de escuchar el evento onerror del guión? Tuve este problema y lo resolví parchando el método de jquery donde se creó la etiqueta de script. Aquí está el código interesante:

// 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;
}

¿Qué te parece esta solución? ¿Es probable que cause problemas de compatibilidad?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top