Подтвердить что ты не робот

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
4b9b3361

Ответ 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, чтобы разрешить пустое тело