jQuery ajax (jsonp) игнорирует тайм-аут и не запускает событие ошибки



чтобы добавить некоторую базовую обработку ошибок, я хотел переписать кусок кода, который использовал $jQuery.getJSON, чтобы вытащить некоторые фотографии из Flickr. Причина для этого заключается в том, что $.getJSON не обеспечивает обработку ошибок и не работает с таймаутами.



начиная с $.getJSON-это просто обертка вокруг $.ajax я решил переписать вещь и удивить сюрпризом, она работает безупречно.



теперь начинается самое интересное. Когда я намеренно вызываю 404 (путем изменения URL) или вызываю сеть для тайм-аута (не будучи подключенным к сетям), событие ошибки вообще не срабатывает. Я в недоумении, что я делаю неправильно. Помощь очень ценится.



вот код:



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

});


Я хотел бы добавить, что этот вопрос был задан, когда jQuery был в версии 1.4.2

777   7  

7 ответов:

jQuery 1.5 и выше имеют лучшую поддержку для обработки ошибок с запросами JSONP. Однако, вы должны использовать $.ajax вместо $.getJSON. Для меня это работает:

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

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

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

тайм-аут, похоже, делает трюк и вызывает обработчик ошибок, когда нет успешного запроса через 10 секунд.

Я немного blogpost на эту тему тоже.

Это известное ограничение с собственной реализацией jsonp в jQuery. Текст ниже от IBM DeveloperWorks

JSONP очень мощный метод для построение мэшапов, но, к сожалению, это не панацея от всех ваших междоменной связи. Оно имеет некоторые недостатки, которые должны быть приняты в серьезного рассмотрения, прежде чем выделение ресурсов на развитие. Прежде всего, нет никакой ошибки обработка JSONP-вызовов. Если динамическая вставка скрипта работает, вы позвоните; если нет, ничего не происходит. Он просто молча терпит неудачу. Например, вы не можете поймать ошибку 404 от сервера. Вы также не можете отменить или перезапустите запрос. Вы можете, однако, тайм-аут после ожидания разумного количество времени. (Будущее в jQuery версии могут иметь функцию прерывания для Запросы JSONP.)

однако есть плагин jsonp, доступный на GoogleCode что обеспечивает поддержку обработки ошибок. Для начала просто внесите следующие изменения в свой код.

Вы можете либо скачать его, или просто добавить ссылку на скрипт в плагин.

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

затем измените свой вызов ajax, как показано ниже:

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

решение, если вы застряли с jQuery 1.4:

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

Это может быть" известным " ограничением jQuery; однако, это не кажется хорошо документированным. Я провел около 4 часов сегодня, пытаясь понять, почему мой тайм-аут не работал.

я переключился на jquery.jsonp и это сработало, как шарм. Спасибо.

похоже, что он разрешен с jQuery 1.5. Я пробовал код выше, и я получаю обратный вызов.

Я говорю "кажется", потому что документация обратного вызова ошибки для jQuery.ajax () по-прежнему имеет следующую записку:

Примечание: этот обработчик не вызывается для междоменных сценариев и запросов JSONP.

плагин jquery-jsonp jQuery, упомянутый в Жозе Базилиоответ Теперь можно найти на GitHub.

к сожалению, документация несколько спартанская, поэтому я привел простой пример:

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

важно Включите параметр callbackParameter в вызов $.jsonp () в противном случае я обнаружил, что функция обратного вызова никогда не вводится в строку запроса вызова службы (текущая по состоянию на версию 2.4.0 из jquery-jsonp).

я знаю, что этот вопрос старый, но проблема обработки ошибок с помощью JSONP все еще не "решена". Надеюсь, это обновление поможет другим, поскольку этот вопрос занимает первое место в Google для "обработки ошибок jquery jsonp".

Как насчет прослушивания события onerror сценария ? У меня была эта проблема, и я решил ее, исправив метод jquery, где был создан тег сценария. Вот интересный фрагмент кода:

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

что вы думаете об этом решении ? Это может вызвать проблемы совместимости ?

Comments

    Ничего не найдено.