Как отозвать функцию на 404 в запросе JSON AJAX с JQuery? - PullRequest
21 голосов
/ 22 марта 2010

Я хочу сделать Ajax-запрос с ответом в JSON. Поэтому я сделал запрос Ajax:

$.ajax({
    url: 'http://my_url',
    dataType: "json",
    success: function(data){
      alert('success');
    },
    error: function(data){
      alert('error');
    },
    complete: function(data) {
      alert('complete')
    }})

Этот код работает хорошо, но когда мой URL посылает мне HTTP-код 404, никакие обратные вызовы не используются, даже полный обратный вызов. После исследования это связано с тем, что мой dataType - «json», поэтому возвращаемое значение 404 - HTML, а анализ JSON не выполнен. Так что никакого обратного вызова.

Есть ли у вас решение для вызова функции обратного вызова при поднятии 404?

РЕДАКТИРОВАТЬ: полный обратный вызов не требует возврата - 404. Если вы хотите URL с 404, вы можете позвонить: http://twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697 именно с этим URL у меня возникла проблема.

Ответы [ 10 ]

19 голосов
/ 22 марта 2010
$.ajax({
    url: 'http://twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697',
    dataType: "json",
    success: function(data) {
        alert('success');
    },
    error: function(data) {
        alert('error');
    },
    complete: function(xhr, data) {
        if (xhr.status != 0)
             alert('success');
        else
             alert('fail');
    }
})
9 голосов
/ 29 марта 2010

С вашей конфигурацией jQuery использует jsonp для транспортировки данных. Это работает путем динамической вставки элемента скрипта и установки URL-адреса на указанное значение. Данные, возвращаемые сервером, затем оцениваются как JavaScript - обычно вызывая предоставленный обратный вызов. Если сервер возвращает 404, очевидно, что содержимое не содержит JavaScript, и обратный вызов никогда не вызывается. Некоторые браузеры поддерживают обработчики ошибок тега script, которые вызываются в этих ситуациях. К сожалению, IE не поддерживает это. Лучший способ обнаружить ошибку - использовать тайм-аут.

В вашем случае вы должны указать дополнительную опцию timeout, которая вызывает вызов обработчика ошибок, если обратный вызов не был вызван вовремя (что было бы в случае ответа 404).

$.ajax({
  url: 'http://my_url',
  timeout: 2000, // 2 seconds timeout
  dataType: "json",
  success: function(data){
    alert('success');
  },
  error: function(data){
    alert('error');
  },
  complete: function(data) {
    alert('complete')
  }
});
4 голосов
/ 23 августа 2012

Если вы хотите обрабатывать ошибки при доступе к API Twitter с помощью Javascript и jsonp, вам необходимо включить параметр suppress_response_codes в ваш запрос.Это заставляет все ответы от Twitter API отвечать 200 OK ответом и включать ошибку.Затем необходимо проверить, содержит ли ответ параметр error или нет.

$.ajax({
  url: "https://api.twitter.com/1/users/show.json",
  dataType: 'jsonp',
  jsonp: "callback",
  data: {
    screen_name: "simongate1337",
    suppress_response_codes: true // <- Important part
  },
  success: function(data) {
    if(data.error) {
      console.log("ERROR: "+data.error);
    } else {
      console.log("Success, got user " + data.screen_name);
    }
  }
});
3 голосов
/ 06 декабря 2013

Используйте statusCode -Опция

$.ajax({
    url: 'http://my_url',
    dataType: "json",
    statusCode: {
        404: function() {
            alert("I could not find the information you requested.");
        }
    },
    success: function(data) {
      alert('success');
    },
    error: function(data) {
      alert('error');
    },
    complete: function(data) {
      alert('complete');
    }
})
2 голосов
/ 01 апреля 2010

Вам не кажется, что проблема не в dataType, а в междоменных запросах, которые вы не можете делать?не, когда вы делаете междоменные запросы:

function handle404(xhr){
    alert('404 not found');
}

function handleError(xhr, status, exc) {
     // 0 for cross-domain requests in FF and security exception in IE 
    alert(xhr.status);
    switch (xhr.status) {
        case 404:
            handle404(xhr);
            break;
    }
}

function dumbRequest() {
    var url = 'http://twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697';
    url = 'http://twitter.com/';    
    url = '/mydata.json';    
//    url = 'mydata.json';    
    $.ajax(
        {url: url,
         dataType: 'json',
         error: handleError}
    );
}
1 голос
/ 31 августа 2011

Только что столкнулся с той же проблемой и увидел другой вопрос упомянул, что jQuery-JSONP (jQuery Plugin) поддерживает перехват 404 ошибок или как они описывают: " восстановление ошибок в случай сбоя в сети или неправильно сформированные ответы JSON "

И работает отлично :)

Вот мой (упрощенный) код для получения подробной информации о видео YouTube через JSONP:

$.jsonp(
{
    url: "https://gdata.youtube.com/feeds/api/videos/ee925OTFBCA",
    callbackParameter: "callback",
    data: 
    {
        alt: "jsonc-in-script",
        v: "2"
    },
    success: function(json, textStatus) 
    { 
        console.log("WEEEEEEEE!"); 
    },
    error: function(xOptions, textStatus) 
    {
        console.error(arguments);
    }
});
1 голос
/ 02 апреля 2010

Знаете ли вы, что, хотя статус HTTP равен 404, фактическое тело является допустимым JSON? Например, эта ссылка имеет следующий JSON:

jsonp1269278524295({"request":"/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697","error":"Not found"})

Таким образом, вы должны проверить, есть ли у ваших данных свойство error в вашей обычной функции обратного вызова.

ОБНОВЛЕНИЕ : по-видимому, даже если фактическое содержимое страницы является допустимым JSON, браузер (я проверял в Firefox) не выполняет его, скорее всего, потому что это 404. Поскольку jQuery должен добавьте элемент script (из-за междоменной проблемы), его JSONP-оболочка никогда не вызывается, и, как следствие, ни ваши обратные вызовы.

Итак, вкратце, я не думаю, что есть способ справиться с этим, не добавляя вручную этот элемент скрипта и не проверяя, была ли ваша предварительно определенная функция обратного вызова вызвана впоследствии.

1 голос
/ 29 марта 2010

Это просто потому, что для dataType установлено значение "json"? Если это так, попробуйте изменить его на text и оценить JSON самостоятельно:

$.ajax({
    url: 'http://twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697',
    dataType: 'text',
    success: function(data, status, xmlHttp) {
        try {
            data = eval('(' + data + ')');
            alert('success');
        } catch (e) {
            alert('json parse error');
        }
    },
    error: function(xmlHttp, status, error) {
        alert('error');
    },
    complete: function(xmlHttp, status) {
        alert('complete');
    }
});
0 голосов
/ 07 апреля 2012

У меня нормально работает следующее решение:)

$.ajax({
    url: 'http://my_url',
    dataType: "json",
    success: function(data){
      alert('success');
    },
    error: function(data){
      alert('error');
    },complete: function(xhr, data) {
        if(data==="parsererror"){
             alert('404');
        }
    } 
});
0 голосов
/ 03 апреля 2010

Вот как я с этим справляюсь. Я проверяю возвращенные данные на наличие ошибок, прежде чем пытаться их использовать. То, что показано ниже, является лишь примером, который вы можете расширить, чтобы более точно соответствовать вашим требованиям. Это также учитывает время ожидания сеанса и другие сценарии ...

Мой начальный звонок:

  $.ajax({ type: 'POST', 
    url: '../doSomething',
    data: 'my data',
    success: function(data) {
      if (HasErrors(data)) return;
      var info = eval('(' + data + ')');
      // do what you want with the info object
    },
    error: function(xmlHttpRequest) {
      ReportFailure(xmlHttpRequest);
    }
  });

И две вспомогательные функции:

function HasErrors(data) {
  if (data.search(/login\.aspx/i) != -1) {
    // timed out and being redirected to login page!
    top.location.href = '../login.aspx';
    return true;
  }
  if (data.search(/Internal Server Error/) != -1) {
    ShowStatusFailed('Server Error.');
    return true;
  }
  if (data.search(/Error.aspx/) != -1) {
    // being redirected to site error reporting page...
    ShowStatusFailed('Server Error. Please try again.');
    return true;
  }
  return false;
}

и

function ReportFailure(msg) {
  var text;
  if (typeof msg == 'string') {
    text = msg;
  }
  else if (typeof msg.statusText == 'string') {
    if (msg.status == 200) {
      text = msg.responseText;
    }
    else {
      text = '(' + msg.status + ') ' + msg.statusText + ': ';
      // use the Title from the error response if possible
      var matches = msg.responseText.match(/\<title\>(.*?)\<\/title\>/i);
      if (matches != null)
      { text = text + matches[1]; }
      else
      { text = text + msg.responseText; }
    }
  }
  // do something in your page to show the "text" error message
  $('#statusDisplay')
    .html('<span class="ui-icon ui-icon-alert"></span>' + text)
    .addClass('StatusError');
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...