轨道 - 使用动态变量修改 %p 的文本



我有一个基本表单,提交后会触发对外部API的创建请求。提交时,将显示带有进度条的阶段值,而不是"提交"按钮。创建过程在外部 API 上需要时间,因此我必须使用while status == 'inactive'每秒运行几个 Show 请求,并在 Show 请求响应status: 'active'时停止。 每个 Show 请求响应还包含一个'stage'属性,该属性显示创建过程的阶段(连接、创建、获取、整理等(。对于每个请求,当前阶段都存储在 @stage 变量中,可以使用ApiRequest.stage访问该变量。每个与 API 相关的东西都在服务文件中。

我的咖啡脚本,使用阶段+进度条更改提交按钮:

$('#new_connection').on 'submit', ->
button = $('#submit_button')
progress = $('.loading')
button.fadeOut 500
setTimeout (->
if button.is(':hidden')
progress.fadeIn 500
return
), 509
return

和阶段+进度条部分:

.loading
%p.center-align#stage <!-- This should display the stage in real time -->
.progress <!-- This is a materializecss progress bar -->
.indeterminate

从提交表单的那一刻起直到最后(它将重定向到创建.html当后台的所有内容都完成时,我如何使用ApiRequest.status实时更改更新#stage中的文本(?

要实时或至少接近实时地显示操作状态,您必须

  • 定期轮询服务器以查看状态是否已更改 - 即每隔一两秒继续点击show终结点,并更新成功回调中的状态标签
  • 或者,您可以实现一种方案,让服务器在使用 WebSockets、长轮询或其他一些技术状态更改时通知页面。

投票就像你开车,你的一个乘客每一秒都在问"我们到了吗?"。它的效率不是很高,尤其是在操作需要很长时间的情况下,因为每n秒发出一个单独的 HTTP 请求,只是返回"仍在进行中"的响应。但它很容易实现,所以如果show动作很快,并且操作本身完成得相当快,那么它可能是一个很好的折衷方案。

另一种方法是让服务器在状态发生更改时通知您。为此,您需要有一个发布者-订阅者基础结构。如果您使用的是 Rails 5,Action Cable 可能是您的最佳选择,因为它内置在 Rails 中。您可以在此处找到不同可用技术的详细比较:在什么情况下,AJAX 长/短轮询比 HTML5 WebSocket 更受欢迎?

如果使用轮询,则可以更新常规 AJAX 调用对showsuccess回调中的状态标签。如果show仅呈现 HTML,则必须从 AJAX 响应数据中解析出新状态:

<!-- example output of show.html.erb -->
<!-- ... -->
<div id="current-status"><%= @status %></div>
<!-- ... -->

纯JavaScript中的示例,用于解析AJAX响应中的页面并获取#current-status<div>的值:

setTimeout(function() {
$.get({
url: "<%= show_page_path %>",
success: function(data) {
var response = $("<div></div>").
append($.parseHTML(data, null, true));
$("#current-status").html(
$("#current-status", response)
);
},
});
}, 1000);

当然,如果您为仅包含状态的show操作添加 JSON 终端节点:

# in the controller
respond_to do |format|
format.html
format.json do
render json: { status: @status }
end
end

然后,您不必执行任何HTML解析:

setTimeout(function() {
$.get({
url: "<%= show_page_path(format: :json) %>",
success: function(data) {
$("#current-status").text(data.status);
},
});
}, 1000);

这些示例未经测试,因此如果不进行一些修改,它们可能无法完美运行。

好的,所以你要做的就是在控制器中创建一个读取变量的方法:@stage = your method here.
format.json { render json: { stage: @stage } }写一个respond_to do |format|
现在,您必须为此自定义控制器方法创建一个路由:get '/your/link', to: 'controller#custom_method', as: 'stage'
剩下的就是通过 Ajax 触发此方法:

$.get({
url: "your/link.json",
success: function(data) {
$('#your_paragraph_id').text(data['stage]);
},
});

你可以把这个 Ajax 调用放在 setInterval 函数中。

最新更新