Backbone model.destroy() вызывает функцию обратного вызова ошибки, даже если она работает нормально?
У меня есть модель Backbone.js, которую я пытаюсь уничтожить, когда пользователь нажимает ссылку в представлении модели. Представление выглядит примерно так (псевдокод, потому что он реализован в CoffeeScript, который можно найти в нижней части вопроса).
var window.ListingSaveView = Backbone.View.extend({
events: {
'click a.delete': 'onDestroy'
},
onDestroy: function(event){
event.preventDefault();
this.model.destroy({
success: function(model, response){
console.log "Success";
},
error: function(model, response){
console.log "Error";
}
});
}
});
Когда я нажимаю ссылку delete
в браузере, я всегда получаю Error
, зарегистрированный на консоли, хотя мой сервер записывает успешное уничтожение связанной записи базы данных и возвращает ответ 200. Когда я обновляю страницу (вызывая повторную визуализацию коллекции из БД), удаляемая модель удаляется.
Интересно, что когда я регистрирую response
в обратном вызове ошибки, он имеет код состояния 200
, указывающий на успех, но также сообщает statusText: "parseerror"
все, что это означает. В моих журналах сервера нет ошибок.
Что я делаю неправильно?
Это ответ с сервера:
Object
abort: function ( statusText ) {
always: function () {
complete: function () {
done: function () {
error: function () {
fail: function () {
getAllResponseHeaders: function () {
getResponseHeader: function ( key ) {
isRejected: function () {
isResolved: function () {
overrideMimeType: function ( type ) {
pipe: function ( fnDone, fnFail ) {
promise: function ( obj ) {
readyState: 4
responseText: " "
setRequestHeader: function ( name, value ) {
status: 200
statusCode: function ( map ) {
statusText: "parsererror"
success: function () {
then: function ( doneCallbacks, failCallbacks ) {
__proto__: Object
Вот действие сервера, которое разрушает, взаимодействует с (Ruby on Rails)
# DELETE /team/listing_saves/1.json
def destroy
@save = current_user.team.listing_saves.find(params[:id])
@save.destroy
respond_to do |format|
format.json { head :ok }
end
end
И вот настоящая реализация CoffeeScript для Backbone View для людей, которые предпочитают это так:
class MoveOutOrg.Views.ListingSaveView extends Backbone.View
tagName: 'li'
className: 'listing_save'
template: JST['backbone/templates/listing_save']
events:
'click a.delete_saved': 'onDestroy'
initialize: ->
@model.bind 'change', this.render
render: =>
renderedContent = @template(@model.toJSON())
$(@el).html(renderedContent)
this
onDestroy: (event) ->
event.preventDefault() # stop the hash being added to the URL
console.log "Listing Destroyed"
@model.destroy
success: (model, response)->
console.log "Success"
console.log model
console.log response
error: (model, response) ->
console.log "Error"
console.log model # this is the ListingSave model
console.log response
Ответы
Ответ 1
@David Tuite комментарий:
"Хорошо, я понял это. Кажется, что Backbone ожидает, что ответ JSON будет сериализацией JSON уничтоженной записи. Однако генераторы контроллеров Rails возвращают только head: ok по умолчанию. Я изменил свой ответ JSON на render json: @listing_save, где @listing_save - это запись, которую я только что уничтожил, и она регистрирует успех.
FYI - когда вы делаете уничтожение, вам не нужно возвращать полный json для уничтоженной модели. вы можете вернуть пустой хэш-код json, и он будет работать нормально. единственный раз, когда вам нужно вернуть json для модели, это сохранить/обновить.
Ответ 2
У меня была такая же проблема. В моем методе удаления на сервере (java) я ничего не возвращал. Просто статус 200/OK (или 204/Нет содержимого). И поэтому проблема "parsererror" была вызвана тем, что jquery пытается преобразовать пустой ответ в JSON, который не удался (поскольку "json" является типом данных по умолчанию).
Мое решение состояло в том, чтобы вместо этого использовать "text" dataType, который можно установить в параметрах:
model.destroy({ dataType: "text", success: function(model, response) {
console.log("success");
}});
Ответ 3
Ваш ответ должен иметь код состояния 204, поскольку вы не будете возвращать какой-либо контент. Поскольку магистральная система использует интерфейс REST, вы должны возвращать разные коды состояния http в зависимости от задачи.
Ответ 4
Вы уверены в своем URL? Добавляете ли вы .json
в конец Backbone.Model url? Поскольку вы проверяете это на своей стороне сервера (reply_to do | format |... end), вы не можете отправить правильный ответ head :ok
Попробуйте использовать этот метод destroy
rails для проверки, если это проблема:
def destroy
@save = current_user.team.listing_saves.find(params[:id])
@save.destroy
head :ok
end
Ответ 5
Используя Slim Framework на сервере LAMP, вы можете добавить Статус ответа в DELETE (или настраиваемые маршруты, которые ничего не возвращают)
$app->response()->status(204);//204 No Content
это также устанавливает Content-Type обратно в text/html, чтобы разрешить пустое тело