Pergunta

Para adicionar um pouco de manipulação de erro básico, eu queria reescrever um pedaço de código que usado do jQuery $ .getJSON para puxar em alguns foto de de Flickr. A razão para isso é que $ .getJSON não fornece tratamento de erros ou trabalhar com limites de tempo.

Desde $ .getJSON é apenas um invólucro em torno $ .ajax eu decidi reescrever a coisa e surpresa surpresa, ele funciona perfeitamente.

Agora, a diversão começa embora. Quando eu deliberadamente causa um 404 (alterando a URL) ou causa a rede para timeout (por não ser-se viciado aos interwebs), o evento de erro não faz fogo, em tudo. Eu estou em uma perda sobre o que eu estou fazendo errado. Ajuda é muito apreciado.

Aqui está o 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);
        }
    });

});

Eu gostaria de acrescentar que esta pergunta foi feita quando jQuery estava na versão 1.4.2

Foi útil?

Solução

jQuery 1.5 e superior têm um melhor suporte para o tratamento de erros com pedidos JSONP. No entanto, você precisa usar o método $.ajax vez de $.getJSON. Para mim, isso funciona:

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

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

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

O tempo limite parece estar a fazer o truque e chamar o manipulador de erro, quando não há pedido de sucesso após 10 segundos.

Eu fiz um pouco blogpost sobre este assunto também.

Outras dicas

Esta é uma limitação conhecida com a implementação jsonp nativa em jQuery. O texto abaixo é de IBM DeveloperWorks

JSONP é uma técnica muito poderosa para construção de mashups, mas, infelizmente, não é uma panacéia para todos os seus necessidades de comunicação de domínio cruzado. isto tem algumas desvantagens que devem ser tomadas em séria consideração antes comprometendo recursos de desenvolvimento. Em primeiro lugar, não há erro manipulação para chamadas JSONP. Se o obras de inserção de script dinâmicas, você obter chamado; se não, nada acontece. Ele só falha silenciosamente. Por exemplo, você não é capaz de capturar um erro 404 a partir do servidor. Também não se pode cancelar ou reinicie o pedido. Você pode, no entanto, tempo limite depois de esperar um razoável quantidade de tempo. (Future jQuery versões podem ter um recurso de anulação de JSONP pedidos.)

No entanto, há um plug-in jsonp disponíveis em GoogleCode que fornece suporte para o erro manipulação. Para começar, basta fazer as seguintes alterações ao seu código.

Você pode baixá-lo, ou apenas adicionar uma referência de script para o plug-in.

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

Em seguida, modificar a sua chamada ajax como mostrado abaixo:

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

A solução se você está preso com jQuery 1.4:

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

Esta pode ser uma limitação "conhecido" do jQuery; no entanto, não parece ser bem documentado. Passei cerca de 4 horas hoje tentando entender por que o meu tempo de espera não estava funcionando.

Mudei para jquery.jsonp e funcionou gostei um encanto. Obrigado.

parece ser resolvido a partir de jQuery 1.5. Eu tentei o código acima e eu começo a chamada de retorno.

Digo "parece ser" porque a documentação do retorno de erro para jQuery.ajax () ainda tem a seguinte nota:

Nota:. Esse manipulador não é chamado para script e JSONP solicitações entre domínios

O jquery-jsonp plugin jQuery mencionado na de José Basilio resposta agora pode ser encontrado na GitHub .

Infelizmente a documentação é um pouco espartano, então eu forneci um exemplo simples:

    $.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 Incluir o callbackParameter na chamada $ .jsonp () caso contrário, eu descobri que a função de retorno nunca é injetado na string de consulta da chamada de serviço (corrente a partir da versão 2.4.0 do jQuery-jsonp).

Eu sei que esta questão é antiga, mas a questão da manipulação usando JSONP erro ainda não está 'resolvida'. Esperemos que esta actualização vai ajudar outras pessoas como esta questão é o topo do ranking no Google para "tratamento de erro jquery jsonp".

Que tal ouvir evento onerror do script? Eu tive esse problema e resolveu por remendar o método de jquery onde a tag script foi criado. Aqui está a parte interessante de código:

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

O que você acha desta solução? É provável que os problemas de compatibilidade causa?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top