为什么涡轮流不更新,除非我添加延迟?



Turbo在JavaScript端很慢,我不得不延迟Ruby端。如果我不延迟服务器响应,页面上就没有涡轮流更新。我的日志显示每个涡轮流都在渲染,所有的作业都被执行和传输。

控制器:

# app/controllers/grids_controller.rb
class GridsController < ApplicationController
def play
@job_id = PlayJob.perform_later(**@grid_data.attributes).job_id # Turbo broadcasts
render :play, status: :created
end
end

Turbo流视图:

<!-- app/views/grids/play.html.erb -->
<%= turbo_stream_from :play, @job_id %>
<div id="grid">
<% unless Rails.env.test? %>
<p><strong>Phase 0</strong></p>
<div class="cells">
<%= image_tag asset_url('loading.gif'), alt: 'loading', class: 'loading' %>
</div>
<% end %>
</div>

涡轮广播:

# lib/grid.rb
class Grid
def play(job_id)
sleep 1 # I am forced to add delay of one second to get turbo to respond!
loop do
broadcast_to :play, job_id
break if phase >= @phases
sleep @phase_duration
next_phase
end
end
def broadcast_to(*streamable)
Turbo::StreamsChannel.broadcast_update_to(
streamable,
target: 'grid',
partial: 'grids/grid',
locals: { grid: self }
)
end
end

下面是我所有应用程序的代码:https://github.com/chiaraani/life-game-web

在您的play动作中,您正在广播到您尚未连接的频道,然后您正在渲染turbo_stream_from连接的play.html.erb。到那时,所有的作业都已完成,这就是为什么当您添加延迟时,有时间连接并查看更新。

你也可以在日志中看到,所有的工作都完成了,然后你看到:

# jobs
# jobs
Turbo::StreamsChannel is streaming from ...

但是没有任何东西可以流。

在提交表单之前,您必须已经连接了turbo_stream_from,并且已经在页面上准备捕获#grid目标:

# app/views/new.html.erb
# NOTE: you can create Play model in `new` action and just do update.
#       this way you have an `id` to broadcast to. I just made a random one
#       in place.
<%= turbo_stream_from :play, (play_id = SecureRandom.uuid) %>
<%= form_with model: @grid_data, url: play_path, builder: GridFormBuilder do |f| %>
# send `id` back to controller
<%= hidden_field_tag :id, play_id %>
<% GridData.attribute_names.each do |attribute| %>
# just use `scope`
<%= f.label attribute, t(attribute, scope: :questions) %> 
<%= f.number_field attribute %>
<% end %>
<%= f.submit %>
<% end %>
<%= tag.div id: "grid" %>
# app/controllers/grids_controller.rb
def create
@grid_data = GridData.new(**grid_params)
respond_to do |format|
if @grid_data.valid?
# pass `id` so we can broadcast to it
@grid_data.to_grid.play(params[:id])
# it just needs to be an empty response, but it has to be `turbo_stream`
format.turbo_stream { render inline: "" } 
else
format.html { render :new, status: :unprocessable_entity }
end
end
end

你可以删除所有sleep延迟,看看它有多快。

相关内容

最新更新