Як виявити помилку jQuery $ .getJSON (або $ .ajax з типом даних, встановленим на 'jsonp'), під час використання JSONP?


76

Чи можна виявити помилку при використанні JSONP з jQuery? Я спробував як $ .getJSON, так і $ .ajax методи, але жоден з них не виявить помилку 404, яку я тестую. Ось те, що я спробував (майте на увазі, що всі вони працюють успішно, але я хочу розглянути справу, коли вона не вдається):

jQuery.ajax({
    type: "GET",
    url: handlerURL,
    dataType: "jsonp",
    success: function(results){
        alert("Success!");
    },
    error: function(XMLHttpRequest, textStatus, errorThrown){
        alert("Error");
    }
});

А також:

jQuery.getJSON(handlerURL + "&callback=?", 
    function(jsonResult){
        alert("Success!");
    });

Я також спробував додати $ .ajaxError, але це теж не спрацювало:

jQuery(document).ajaxError(function(event, request, settings){
   alert("Error");
});

Заздалегідь дякую за відповіді!


Що поганого у використанні 'error: function () {}' ??
Джеймс,

1
Це не стрільба. (Пам'ятайте, що це JSONP).
Енді,

Відповіді:


51

Здається, запити JSONP, які не повертають успішного результату, ніколи не викликають жодної події, успіху чи невдачі, а в кращу чи гіршу сторону це, мабуть, задумано.

Після пошуку їх відстежувача помилок, є патч, який може бути можливим рішенням із використанням зворотного виклику з часом очікування. Див. Звіт про помилку № 3442 . Якщо ви не можете виявити помилку, ви можете принаймні таймаут, чекаючи розумного часу на успіх.


Посилання на звіт про помилку № 3442 порушено. Це, мабуть, правильне посилання: Квиток № 3442 (закрите доповнення: виправлено)
hippietrail

Домовились !!! одне питання, хоча я роблю виклик JSONP і отримую помилку 404, але я не отримую 406 і 401 ??? чому ??? stackoverflow.com/questions/18570486/…
Хітеш

неправильна відповідь, правильною є та, яка описує використання .fail (function ())
jumpjack

Цю відповідь не слід вважати правильною (більше?) Stackoverflow.com/a/19075701/2617354 - це правильний шлях.
Daywalker

53

Ось моя велика відповідь на подібне питання.

Ось код:

jQuery.getJSON(handlerURL + "&callback=?", 
    function(jsonResult){
        alert("Success!");
    })
.done(function() { alert('getJSON request succeeded!'); })
.fail(function(jqXHR, textStatus, errorThrown) { alert('getJSON request failed! ' + textStatus); })
.always(function() { alert('getJSON request ended!'); });

12
Я не розумію, чому це не має більше голосів. Очевидно, саме так має відбуватися обробка помилок. Чому прийнята відповідь говорить: "Здається, запити JSONP, які не повертають успішний результат, ніколи не викликають жодної події, успіху чи невдачі", коли це, очевидно, просто не відповідає дійсності ??? Речі, яких я не розумію.
phil294

Прочитавши трохи уважніше, я думаю, це має зробити, що в 2008 році дещо інше було в jQuery;)
Daywalker,

@Daywalker так, методи успіху / помилки / завершення були припинені та вилучені станом на JQuery 3.0 ( api.jquery.com/jQuery.get )
user2314737

16

Виявлення проблем JSONP

Якщо ви не хочете завантажувати залежність, ви можете виявити стан помилки самостійно. Це легко.

Ви зможете виявити помилки JSONP лише за допомогою певного часу очікування. Якщо протягом певного часу немає дійсної відповіді, то припустіть помилку. Однак помилка може бути в основному будь-якою.

Ось простий спосіб перевірити наявність помилок. Просто використовуйте successпрапор:

var success = false;

$.getJSON(url, function(json) {
    success = true;
    // ... whatever else your callback needs to do ...
});

// Set a 5-second (or however long you want) timeout to check for errors
setTimeout(function() {
    if (!success)
    {
        // Handle error accordingly
        alert("Houston, we have a problem.");
    }
}, 5000);

Як згадував thedawnrider у коментарях, ви можете замість цього використовувати clearTimeout:

var errorTimeout = setTimeout(function() {
    if (!success)
    {
        // Handle error accordingly
        alert("Houston, we have a problem.");
    }
}, 5000);

$.getJSON(url, function(json) {
    clearTimeout(errorTimeout);
    // ... whatever else your callback needs to do ...
});

Чому? Читати далі ...


Ось як JSONP працює в двох словах:

JSONP не використовує XMLHttpRequest, як звичайні запити AJAX. Натомість він вводить a<script> тег на сторінку, де атрибут "src" є URL-адресою запиту. Зміст відповіді обертається функцією Javascript, яка потім виконується при завантаженні.

Наприклад.

Запит JSONP: https://api.site.com/endpoint?this=that&callback=myFunc

Javascript введе цей тег сценарію в DOM:

<script src="https://api.site.com/endpoint?this=that&callback=myFunc"></script>

Що відбувається, коли a <script> тег додається до DOM? Очевидно, це виконується.

Отже, припустимо, відповідь на цей запит дав результат JSON, такий як:

{"answer":42}

Для браузера це те саме, що і джерело сценарію, тому він виконується. Але що відбувається, коли ви виконуєте це:

<script>{"answer":42}</script>

Ну нічого. Це просто об’єкт. Він не зберігається, не зберігається, і нічого не відбувається.

Ось чому запити JSONP обертають свої результати у функції. Сервер, який повинен підтримувати серіалізацію JSONP, бачить callbackвказаний вами параметр і замість цього повертає це:

myFunc({"answer":42})

Тоді замість цього виконується:

<script>myFunc({"answer":42})</script>

... що набагато корисніше. У цьому випадку десь у вашому коді є глобальна функція, яка називається myFunc:

myFunc(data)
{
    alert("The answer to life, the universe, and everything is: " + data.answer);
}

Це воно. Це «магія» JSONP. Тоді вбудувати перевірку очікування дуже просто, як показано вище. Зробіть запит і одразу після цього розпочніть тайм-аут. Через X секунд, якщо ваш прапор все ще не встановлено, запит минув.


1
Ви також можете використовувати, jsonpFailCheck = setTimeout(...)а потім замість того success=true, щоб використовуватиclearTimeout(jsonpFailCheck)
iancoleman

14

Я знаю, що це запитання трохи давнє, але я не побачив відповіді, що дає просте рішення проблеми, тому я вирішив поділитися своїм "простим" рішенням.

$.getJSON("example.json", function() {
      console.log( "success" );
}).fail(function() { 
      console.log( "error" ); 
}); 

Ми можемо просто використовувати .fail()зворотний дзвінок, щоб перевірити, чи не сталася помилка.

Сподіваюся, це допомагає :)


2
Зверніть увагу, що це працює лише у версії 2.x (яка втратила підтримку IE <= 8), а не в 1.x
Laurens Rietveld

@LaurensRietveld Підтримується з v1: api.jquery.com/jQuery.getJSON
Farhan Ahmad

3

Якщо ви співпрацюєте з постачальником, ви можете надіслати інший параметр рядка запиту, який є функцією, для зворотного виклику, коли виникає помилка.

? callback =? & error =?

Це називається JSONPE, але це зовсім не стандартний стандарт.

Потім постачальник передає інформацію функції помилок, щоб допомогти вам діагностувати.

Хоча це не допомагає з помилками comm - jQuery потрібно було б оновити, щоб також повернути функцію помилки під час очікування, як у відповіді Адама Беллера.


2

Здається, це зараз працює:

jQuery(document).ajaxError(function(event, request, settings){
   alert("Error");
});

Тільки для jquery 2.x, а не 1.x
Laurens Rietveld

1

Я використовую це для виявлення помилки JSON

try {
   $.getJSON(ajaxURL,callback).ajaxError();
} catch(err) {
   alert("wow");
   alert("Error : "+ err);
}

Редагувати: Ви також можете отримати повідомлення про помилку. Це дасть вам зрозуміти, в чому саме помилка. Спробуйте дотримуватися синтаксису в блоці catch

alert("Error : " + err);

3
Як можна спробувати / зловити на асинхронний дзвінок? Дзвінок закінчується негайно щодо спроби / лову. Зворотний виклик або будь-яка помилка виникає пізніше, довго після того, як ми залишимо область дії цього коду .
Пропало кодування

0

Мейбі це працює?

.complete(function(response, status) {
    if (response.status == "404")
        alert("404 Error");
    else{
        //Do something
    }   
    if(status == "error")
        alert("Error");
    else{
        //Do something
    }
});

Я не знаю, коли статус переходить у режим "помилки". Але я протестував його на 404, і він відповів


навіть ми можемо перевірити стан відповіді на наявність помилок. Краще ми можемо використовувати функцію помилок.
iamjustcoder

0

ви явно обробляєте будь-який номер помилки, додаючи цей атрибут у запит ajax:

statusCode: {
        404: function() {
          alert("page not found");
        }
    }

отже, ваш код повинен бути таким:

jQuery.ajax({
type: "GET",
statusCode: {
        404: function() {
          alert("page not found");
        }
},
url: handlerURL,
dataType: "jsonp",
success: function(results){
    alert("Success!");
},
error: function(XMLHttpRequest, textStatus, errorThrown){
    alert("Error");
}
});

сподіваюся, це допоможе вам :)


0

Я також розмістив цю відповідь у переповненні стека - обробка помилок у викликах getJSON

Я знаю, що минув якийсь час, коли хтось відповів тут, і плакат, мабуть, вже отримав свою відповідь або звідси, або звідкись ще. Однак я думаю, що ця публікація допоможе кожному, хто шукає спосіб відстежувати помилки та час очікування під час виконання запитів getJSON. Тому нижче моєї відповіді на запитання

Структура getJSON така (знайдена на http://api.jqueri.com ):

$(selector).getJSON(url,data,success(data,status,xhr))

більшість людей реалізують це за допомогою

$.getJSON(url, datatosend, function(data){
    //do something with the data
});

де вони використовують URL-адресу var для надання посилання на дані JSON, datatosend є місцем для додавання "?callback=?" змінних та інших змінних, які необхідно надіслати, щоб отримати правильні дані JSON, і функцію успіху як функцію для обробки даних .

Однак ви можете додати змінні стану та xhr у свою функцію успіху. Змінна стану містить один із таких рядків: "успіх", "немодифікований", "помилка", "час очікування" або "помилка синтаксичного аналізатора", а змінна xhr містить повернутий об'єкт XMLHttpRequest ( знайдений на w3schools )

$.getJSON(url, datatosend, function(data, status, xhr){
    if (status == "success"){
        //do something with the data
    }else if (status == "timeout"){
        alert("Something is wrong with the connection");
    }else if (status == "error" || status == "parsererror" ){
        alert("An error occured");
    }else{
        alert("datatosend did not change");
    }         
});

Таким чином, легко відстежувати тайм-аути та помилки, не застосовуючи власний трекер тайм-ауту, який запускається після виконання запиту.

Сподіваюся, це допомагає комусь, хто все ще шукає відповіді на це питання.


Вибачте, але це нічого не дає з jQuery 2.2.3.
PhilPhil
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.