我有一个 Rails 应用程序,我使用 gridList 显示图表图书馆。图表数据是使用 AJAX 从 Controller 方法(JSON 格式)异步获取的。当页面最初加载时,每个网格列表项都会显示加载图标,同时对服务器进行 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 调用的设计是否正确?我希望图表在数据可用时加载,而不是最后一次全部加载。
最佳答案
多线程服务器并不一定意味着请求是并行处理的。
使用多个 AJAX 请求来加载数据不一定是问题(它确实会带来一些开销),但是如果您需要加载重叠的资源/记录来回答每个请求,您可能想问自己一个问题:“为什么不加载单个请求中的所有数据点?”例如,您可以使用索引请求并提供数据点的边界,仅以 JSON 形式返回边界之间的数据点。
在您的情况下,您可以通过向 GET/users/:user_id/charts.json
发送请求来请求一个用户的所有图表来加载所有数据点。假设您有路线:
resources :users, only: [] do
resources :charts, only: :index
end
加速请求的其他可能的解决方案是:
- 通过使用
#includes
优化数据库查询 (n + 1) 问题从数据库获取时。您可以通过查看服务器日志轻松判断这是否是一个问题。 - 使用轻量级算法优化繁重的计算。这不太容易被发现。如果您的请求需要很长时间但没有执行大量 SQL 查询,您可能需要放下几个断点,通过从一个断点跳到另一个断点来查看所有时间都花在哪里,并了解需要多长时间。在某些情况下,您可以通过分组、求和、取平均值等方式将这些计算插入数据库。
- 为您的服务器分配更多资源,这可以加快请求处理速度。您可以分配多个工作线程来处理并行请求,或者分配更多线程来更快地处理请求。例如。
bundle exec puma --workers 3 --threads 0:16
(0:16) 是默认值,传递大于 1 的工作线程数将激活集群模式(请参阅bundle exec puma --帮助
)。 - 升级开发机器的硬件。更好的 CPU 或 SSD 可能会加快速度。
- 使用负载均衡器,如 NGINX平衡多台机器的负载。
关于javascript - 多个同时发生的 AJAX GET 请求会阻塞服务器,直到返回数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51711721/