【问题标题】:Backbone model.destroy() invoking error callback function even when it works fine?骨干model.destroy()即使工作正常也会调用错误回调函数?
【发布时间】:2011-11-10 10:18:31
【问题描述】:

我有一个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

下面是 Backbone 视图的实际 CoffeeScript 实现,供喜欢这样的人使用:

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

【问题讨论】:

  • 如果有的话,你能粘贴服务器发回的任何东西(使用 firebug 或其他东西打开响应)吗?
  • 编辑了我的问题以包含响应
  • 哦。好吧,坦率地说..这不是一个有效的回应。它很可能在侦听 JSON 响应.. 并且不知何故你没有给它一个。我不记得我们在工作中为 rails 使用了什么,但它类似于 to_json,而不仅仅是 'json'(我不是 ruby​​ 专家.. 甚至是新手.. 所以我忍不住过去了)跨度>
  • 好吧,我想通了。 Backbone 似乎期望 JSON 响应是已销毁记录的 JSON 序列化。然而,Rails 控制器生成器默认只返回head :ok。我将 JSON 响应更改为 render json: @listing_save,其中 @listing_save 是我刚刚销毁的记录,它注册成功。
  • 您确定您的网址吗?我的意思是您是否在 Backbone.Model url 的末尾附加了 .json ?由于您在服务器端 (respond_to do |format| ... end) 进行了检查,因此您可能无法发送正确的 `head :ok` 响应...

标签: javascript ruby-on-rails ruby-on-rails-3 backbone.js javascript-framework


【解决方案1】:

在 LAMP 服务器上使用 Slim 框架,您可以将 Response Status 添加到 DELETE 路由(或不返回任何内容的自定义路由)

$app->response()->status(204);//204 No Content

这也将 Content-Type 设置回 text/html 以允许空正文

【讨论】:

    【解决方案2】:

    @David Tuite 评论:

    “好的,我想通了。似乎 Backbone 期望 JSON 响应是已销毁记录的 JSON 序列化。但是,Rails 控制器生成器默认仅返回 head :ok。我将 JSON 响应更改为render json: @listing_save 其中@listing_save 是我刚刚销毁的记录,它注册成功。”

    仅供参考 - 当您进行销毁时,您无需返回已销毁模型的完整 json。您可以返回一个空的 json 哈希,它会正常工作。唯一需要为模型返回 json 的时间是保存/更新。

    【讨论】:

    • 好的,你可以得到积分。即使我做了一半的工作;)
    • backbone 对 rails json 结果非常敏感
    • 虽然您不必退回模型,但有时这样做非常好。这实际上是一种不错的方法的一种情况是,当您不使用 destroy 的 {wait: true} 参数时——这样,如果操作失败,您可以轻松地将模型重新添加到集合中,以保留集合已更新。
    • 返回一个空的“null”响应也有效(结合 200 状态码)。
    【解决方案3】:

    我遇到了同样的问题。在服务器(java)上的删除方法中,我没有返回任何内容。只是状态 200/OK(或 204/无内容)。因此“parsererror”问题是由于 jquery 试图将空响应转换为 JSON 导致失败(因为“json”是默认数据类型)。

    我的解决方案是改用“文本”数据类型,可以在选项中设置:

    model.destroy({ dataType: "text", success: function(model, response) {
      console.log("success");
    }});
    

    【讨论】:

    • 不错的收获。谢谢。
    • 我也用过model.destroy({contentType: false, processData: false})。
    【解决方案4】:

    您的回复必须有状态码 204,因为您不会返回任何内容。由于主干使用 REST 接口,因此您应该根据任务返回不同的 http 状态代码。

    【讨论】:

      【解决方案5】:

      您确定您的网址吗?您是否在 Backbone.Model url 的末尾附加了 .json ?由于您在服务器端检查此内容(respond_to do |format| ... end),您可能无法发送正确的 head :ok 响应

      尝试使用destroy rails 方法来测试是否是问题所在:

      def destroy
        @save = current_user.team.listing_saves.find(params[:id])
        @save.destroy
        head :ok
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多