jquery 不会在 $.ajax 上为 rails 标准 REST DELETE 答案调用成功方法

Posted

技术标签:

【中文标题】jquery 不会在 $.ajax 上为 rails 标准 REST DELETE 答案调用成功方法【英文标题】:jquery doesn't call success method on $.ajax for rails standard REST DELETE answer 【发布时间】:2011-06-15 01:24:13 【问题描述】:

可能这样的问题并不新鲜,但我没有找到类似的东西。我有这样的 jQuery 代码:

$.ajax( 
  url : ('/people/'+id), 
  type : 'DELETE', 
  dataType : 'json', 
  success : function(e) 
    table.getItems(currentPage);
  
);

我的 Rails 控制器如下所示:

def destroy
    @person = Person.find(params[:id])
    @person.destroy

    respond_to do |format|
      format.html  redirect_to(people_url) 
      format.json   render :json => @person, :status => :ok 
    end
end

这是有效的。

但是当我使用以下(由标准生成)时,success 回调不会被调用:

def destroy
    @person = Person.find(params[:id])
    @person.destroy

    respond_to do |format|
      format.html  redirect_to(people_url) 
      format.json   head :ok 
    end
end

rails 3.0.3jQuery 1.4.2Firefox 3.6.13 下测试。 Firebug 说,该查询在两种情况下都被触发并返回 200 OK,在这两种情况下项目也被删除。但在第二种情况下,不会调用回调。

REST 是否有显着差异,有没有办法通过使用脚手架控制器来利用 jQuery?

【问题讨论】:

两个请求是否都返回了有效的 JSON?你可以用 Charles 嗅探一下,或者用 curl 手动击打它们,看看会发生什么? 您的网址中缺少引号,.. 以防万一。 在我为问题准备代码时出现了缺少的 qoute :) dorkitude,据我所知,在第二种方式中它完全返回空答案,只有 200 OK 标头,这是推荐的 REST 方式。第一种方法返回有效的 JSON,但不建议将此类答案用于资源删除 REST 请求。 这个骗子有一个很好的答案,***.com/questions/12407328/… 【参考方案1】:

我遇到过几次,答案看似简单。

您在 $.ajax 调用中使用了dataType : 'json',因此 jQuery 期待 JSON 响应。使用head :ok,Rails 返回一个包含单个空格 (http://github.com/rails/rails/issues/1742) 的响应,jQuery 不接受它作为有效的 JSON。

所以如果你真的希望得到一个错误或一个空的 200 OK 标头,只需在你的请求中设置 dataType : 'html' 它应该可以工作(如果你不设置 dataType,jQuery 会尝试猜测什么类型是基于响应头等,仍然可以猜到json,在这种情况下你仍然会遇到这个问题)。如果您确实希望返回 JSON,而不是使用 head :ok 渲染对 JSON 有效的内容(请参阅 cmets),或者按照 @Waseem 的建议使用 head :no_content

【讨论】:

在这种情况下你会怎么做才能返回失败? 更好的方法是使用head :no_content。见***.com/a/12751298/100466 和github.com/rails/rails/issues/1742 我遇到了类似的问题,因为 Rails 表单 (simple_form) 中缺少数据类型。以为我会交叉引用这个线程***.com/questions/10839771/… 由<%= simple_form_for @book, :html => :'data-type' => :json, :remote => true do |f| %> 解决 在我通过 :json 返回哈希之前对我不起作用 ":json => 'message' => 'delete completed' " 与@AshBlue 一样,将字符串作为JSON 返回不起作用。我最终返回 nil 并返回一个状态码:render json: nil, status: :ok【参考方案2】:

GearHead 是正确的,只是 jQuery 解析器现在实际上足够聪明,可以将空字符串响应视为 null 而不会尝试解析它。

但是,如果您的呼叫有时会收到 json,有时会收到 head 响应,并且您无权访问服务器或不想更改所有 head 呼叫,您可以执行此替代解决方案:

问题在于,当您使用 head 时,Rails 会发送一个空格作为空响应(请参阅此处:How to return truly empty body in rails? i.e. content-length 0)

在撰写本文时,jQuery parseJSON 函数的相关部分如下所示:

parseJSON: function( data ) 
    if ( typeof data !== "string" || !data ) 
        return null;
    

    // Make sure leading/trailing whitespace is removed (IE can't handle it)
    data = jQuery.trim( data );

    // Attempt to parse using the native JSON parser first
    if ( window.JSON && window.JSON.parse ) 
        return window.JSON.parse( data );
    

如您所见,jQuery 正在测试数据是否为空字符串 修剪它之前。然后它会尝试JSON.parse(""),您可以在控制台中看到这会导致错误,并通过catch 语句触发ajax 错误回调。

有一个简单的解决方法。 jQuery 允许您在请求一种数据类型并返回另一种数据类型时使用转换器。更多详情请看这里:http://api.jquery.com/extending-ajax/

由于 rails head 响应呈现为文本,您可以简单地定义一个文本到 json 转换器,该转换器将在尝试解析响应之前修剪响应。只需添加这个 sn-p:

// deal with rails ' ' empty response
jQuery.ajaxSetup(
  converters: 
    "text json": function (response) 
      jQuery.parseJSON($.trim(response))
    
  
)

【讨论】:

仅供参考,jQuery.parseJSON 只是一个passthrough to JSON.parse,它会在空字符串上引发异常(“输入意外结束”)。所以这应该明确检查空响应($.trim(response).length == 0)和return null【参考方案3】:

这有时是由旧版本的 jQuery 验证插件引起的。如果您使用此插件,有时会导致此问题。如果适用于您的情况,有一个更新可以解决此问题。

或者,您可以通过以下方式设置错误处理程序来找出问题所在:

$.ajaxSetup()$.ajaxError()

这可能会返回解析错误。较新版本的 jQuery 因对 JSON 解析非常严格而臭名昭著。

【讨论】:

不,我不使用任何 jQuery 插件(除了我自己编写的一些插件,但它们对 ajax 没有影响)。而且我知道,在所描述的情况下,服务器返回空答案,而 jquery 可能无法解析它。我想知道是否有一种很好的方法可以让它与这个 empty 答案一起工作。 我假设任何无法解析的东西,包括空答案都会触发 ajaxError 回调,所以你可以在那里为它设置一个处理程序。

以上是关于jquery 不会在 $.ajax 上为 rails 标准 REST DELETE 答案调用成功方法的主要内容,如果未能解决你的问题,请参考以下文章

无法在 ajax jquery 上为 release() 获取 jcrop 对象

jQuery绑定ajax:成功在rails 3应用程序中无法用于新创建的(ajax)项目

jQuery 表单插件 + Ajax 文件上传 + Rails

rails3 rails.js 和 jquery 捕获 ajax 请求的成功和失败

Rails 3 UJS Ajax 模式/策略,哪个更好?

如何使用 rails 和 jquery 优化 ajax 搜索