多个同时的AJAX GET请求阻塞服务器,直到返回数据

时间:2018-08-06 16:10:30

标签: javascript ruby-on-rails ajax

我有一个Rails应用程序,其中使用gridList库显示图表。使用AJAX从控制器方法(JSON格式)异步获取图表数据。最初加载页面时,每个gridlist项都显示加载图标,并同时对服务器进行ajax调用以获取数据。每个单独的网格项目都进行单独的ajax调用。图表呈现正确,但是问题在于,在进行AJAX调用时,服务器不会响应任何其他请求,例如刷新页面或更改路线。它会被阻塞,直到所有图表都加载完毕,此后才发生先前调用的操作。

这是服务器端的问题,因为正在进行AJAX调用时,前端的javascript代码可以正常工作。

使用以下所示的局部渲染网格项

%li.grid_item{ data: { id: chart.id } }
 .chart-loading
   // loading icon
 .chart-content.hide
   // chart-content currently hidden.

:javascript
 var chart_id = "#{chart.id}"
 $.ajax({
   url: "#{get_data_charts_path(chart.id)}",
   success: function (res) {
     var data = JSON.parse(res)
     hideLoadingChart(chart_id) // hides loading and shows chart-content
     renderChart(data) // plots chart for the data
   }
 })

然后使用以下命令调用局部函数-

.grid-container
 %ul#grid.grid
  = render partial: 'chart', collection: @current_user.get_charts

可能是问题所在。向服务器发出新请求时,是否有办法取消所有当前的AJAX调用。
我在为每个图表进行多次AJAX调用的设计是否正确?我希望图表在数据可用时加载,而不是在最后一次加载。

2 个答案:

答案 0 :(得分:1)

多线程服务器不一定意味着请求是并行处理的。

使用多个AJAX请求加载数据不一定是问题(确实会带来一些开销),但是,如果您需要加载重叠的资源/记录来回答每个请求,则可能要问自己一个问题:“为什么不加载单个请求中的所有数据点?”例如,您可以使用索引请求并提供数据点的边界,仅将边界之间的数据点作为JSON返回。

在您的情况下,您可以通过向GET /users/:user_id/charts.json发送请求以请求一个用户的所有图表来加载所有数据点。假设您有路线:

resources :users, only: [] do
  resources :charts, only: :index
end

其他加快请求速度的可能解决方案是:

  1. 从数据库中获取数据时,通过使用#includes来优化数据库查询(n + 1)问题。您可以通过查看服务器日志轻松查看这是否有问题。
  2. 使用轻量级算法优化您的繁重计算。这不太容易发现。如果您的请求花费了很长时间,但又没有执行很多SQL查询,则您可能希望放下几个断点,并通过从一个断点跳到另一个断点来查看所有时间,并了解一下需要花费多长时间。在某些情况下,您可以通过分组,求和,取平均值等将这些计算推入数据库。
  3. 向服务器分配更多资源,这可以加快请求处理速度。您可以分配多个工作线程来处理并行请求,也可以分配更多线程来更快地处理请求。例如。默认为bundle exec puma --workers 3 --threads 0:16(0:16),如果工人数大于1,则会激活集群模式(请参见bundle exec puma --help)。
  4. 升级开发机器的硬件。更好的CPU或SSD可能会加快速度。
  5. 使用NGINX之类的负载均衡器来平衡多台计算机上的负载。

答案 1 :(得分:0)

您可以查看$.Deffered,它可以用来链接多个ajax调用以使其顺序执行。您的服务器一次只会收到一个Ajax调用,下一个将在第一个完成后进行。您的服务器可以自由响应其他请求。