Что изменилось в jQuery 1.9, чтобы вызвать сбой вызова $.ajax с ошибкой синтаксиса
Я делаю вызов REST DELETE, который возвращает 204. В jQuery 1.8.3 это работает и выполняет обратный вызов request.done. Но если я использую 1.9, он переходит к request.fail с parsererror в textStatus и "SyntaxError: Неожиданный конец ввода" в errorThrown.
remove = function (complete) {
var self = this;
var request = $.ajax({
context: self,
url: "/v1/item/" + itemId,
dataType: "json",
type: "DELETE"
});
request.done(removeCallback);
request.fail(function (xhr, textStatus, errorThrown) {
alert(errorThrown);
});
},
Кто-нибудь знает, что изменилось в 1.9, что может привести к сбою, и что нужно изменить, чтобы это исправить?
Итак, отвечая на мой собственный вопрос, похоже, что это на самом деле проблема:
Из руководства по обновлению jQuery
jQuery.ajax, возвращающий результат JSON пустой строки
До 1.9 ajax-вызов, который ожидал возвращаемый тип данных JSON или JSONP, рассматривал возвращаемое значение пустой строки как успешный случай, но возвращал нулевое значение обработчику успеха или обещанию. Начиная с версии 1.9, пустая строка, возвращаемая для данных JSON, считается искаженным JSON (потому что это так); это теперь выдаст ошибку. Используйте обработчик ошибок, чтобы ловить такие случаи.
Итак, если удалить dataType
dataType: "json",
Работает в jQuery 1.8.3 и 1.9.
3 ответа
Ответ HTTP 204 не является пустой строкой: это означает, что данных нет. Это правильный ответ для операций удаления и обновления.
Это похоже на ошибку, введенную в JQuery 1.9.
Причина, по которой удаление свойства dataType исправляет это, заключается в том, что при установке значения "json" JQuery пытается выполнить синтаксический анализ содержимого с использованием JSON.parse, что приводит к сбою. Из билета:
Это не приведет к сбою с любым другим dataType, кроме "json", потому что регрессия происходит из-за повторного выравнивания parseJSON с собственным JSON.parse (исключение для значений null/undefined).
Не пытайтесь использовать обходной путь, предложенный в заявке на добавление обработчика для 204 через свойство statusCode, потому что будет сработать и этот обработчик, и обработчик ошибок. Возможное решение заключается в следующем:
$.ajax(url, {
type: "DELETE",
dataType: "json",
error: function (error) {
if (error.status === 204) {
// Success stuff
}
else {
// fail
}
}});
У меня была очень похожая проблема, и вы помогли мне найти мой ответ - так что спасибо. Мое решение, однако, немного отличается, поэтому я решил поделиться им.
Как указано в вопросе, на веб-сайте JQuery говорится:
До 1.9 ajax-вызов, который ожидал возвращаемый тип данных JSON или JSONP, рассматривал возвращаемое значение пустой строки как успешный случай, но возвращал нулевое значение обработчику успеха или обещанию. Начиная с версии 1.9, пустая строка, возвращаемая для данных JSON, считается искаженным JSON (потому что это так); это теперь выдаст ошибку. Используйте обработчик ошибок, чтобы ловить такие случаи.
Я передавал данные JSON методу на моем сервере с "void" в качестве возвращаемого типа, потому что мне не нужно было ничего делать с возвращенными данными в функции успеха. Вы больше не можете возвращать ноль при передаче JSON в запросе AJAX в JQuery 1.9 +. Однако это было возможно в предыдущих версиях JQuery.
Чтобы перестать получать сообщение об ошибке и вместо этого запустить функцию успеха, вы просто должны вернуть действительный JSON в свой запрос AJAX. Неважно, что вы передаете, если это действительно, потому что (в любом случае, в моем случае) вы не используете возвращенные данные.
Кажется, проблема в том, что jQuery обрабатывает пустое тело (где Content-Length равно 0) ответа 204 как "". Это одна из интерпретаций, но недостатком является то, что "" обрабатывается как любая другая строка ответа. Поэтому, если вы вызвали jQuery.ajax() с параметром dataType:json, jQuery попытается преобразовать "" в объект и выдает исключение ("" является недопустимым JSON).
jQuery ловит исключение и восстанавливает, но если вы предпочитаете вообще избегать исключения (в вашей среде разработки), вы можете сделать что-то вроде следующего. Добавьте параметр "преобразователи" в jQuery.ajax() и используйте его для изменения "" ответов на пустые значения (я делаю это, когда dataType равен json). Что-то вроде:
var ajax_options =
{
/* ... other options here */
"converters" :
{
"text json" :
function( result )
{
if ( result === "" ) result = null;
return jQuery.parseJSON( result );
}
}
};
var dfd = jQuery.ajax( ajax_options );