【问题标题】:jQuery ajax requests to Rails server doubling each time每次对 Rails 服务器的 jQuery ajax 请求加倍
【发布时间】:2011-11-04 17:45:38
【问题描述】:

我已经设置了一个简单的演示应用程序(包含用户和消息)来测试同时使用 jQuery、Ajax 和 Rails。这个想法是,当您将鼠标悬停在用户索引页面上的用户行上时,该页面将使用 Ajax 加载该用户的第一条消息。这在功能上是“有效的”,但是每次鼠标悬停时服务器获取数据的 GET 请求数量会翻倍,直到页面变慢到爬行为止。谁能帮我弄清楚为什么会这样?

显示输出的用户 index.html.erb 如下所示:

  ...
<% @users.each do |user| %>
    <tr class="user_name" id="<%=user.id %>">
       <td><%= user.name %></td>
       <td><%= user.email %></td>
       <td><%= link_to 'Show', user %></td>
       <td><%= link_to 'Edit', edit_user_path(user) %></td>
       <td><%= link_to 'Destroy', user, confirm: 'Are you sure?', method: :delete %></td>
    </tr>
   <% end %>
</table>

<div id="first_message"></div>
...

我的基于 jQuery 的 Ajax 代码(在 assets/ajax.js 中)如下所示:

$(document).ready(function () {
  $('.user_name').mouseover(function() {
    var userId = $(this).attr('id');
    $('#first_message').load(window.location + userId + "/first_message");
  });
});

我添加了以下路由来处理消息加载:

match 'users/:id/first_message' => 'users#first_message'

处理请求的控制器如下所示:

class UsersController < ApplicationController
   def first_message
     @user = User.find(params[:id])

     respond_to do |format|
        format.html # first_message.html.erb
     end
   end

最后,Ajax 请求的 html 响应页面 (first_message.html.erb) 如下所示:

<h3> <%= @user.name %>'s first message: </h3>
<% if @user.messages.length > 0  %>
    <%= @user.messages[0].content %>
<% else  %>
      ...
<% end %>

有什么想法吗?

【问题讨论】:

    标签: jquery ruby-on-rails ajax


    【解决方案1】:

    我假设下面这一行将完整地加载到您的 first_message.html.erb 文件中,包括需要您的 ajax.js 文件的布局。因此,您的ajax.js 文件会被一遍又一遍地包含在内。

    $('#first_message').load(window.location + userId + "/first_message");
    

    您可以将 first_message 视图转换为部分视图,或者您可以告诉它不要使用所有 JS 文件等呈现布局:

    format.html { render :layout => false } # first_message.html.erb
    

    【讨论】:

      【解决方案2】:

      除了 Dylan Markow 提到的关于您的布局的内容之外,您的 JS 中还有一些性能问题:

      mouseover 事件也会在光标进入子元素时触发,因此在这种情况下,每次您将鼠标悬停在 td 上时。您应该使用mouseenter 来避免这种情况。

      http://api.jquery.com/mouseover/

      在您检索到数据后,您应该取消绑定事件,这样您就不会再次获取相同的信息:

      $(function () {
        $('.user_name').mouseenter(function() {
          var userId = $(this).attr('id');
          $('#first_message').load(window.location + userId + "/first_message");
          $(this).unbind('mouseenter');
        });
      });
      

      当然,您会丢失这些数据,因为您没有存储它(选择改为使用load)。您可能应该使用$.get 并保留数据(您可以通过$(this).data('first-message', httpResponseData); 将其与tr 元素一起存储)。

      【讨论】:

        【解决方案3】:

        不完全确定,但看起来在将 HTML 放入 div#first_message 之后,布局也会再次呈现,从而导致 mouseover 事件再次绑定。这会导致 get 请求调用成倍增加。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-07
          • 2020-10-20
          • 1970-01-01
          • 2017-01-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多