Rails - 用动态变量修改 %p 的文本
Rails - modify text of %p with dynamic variable
我有一个基本表单,提交后会触发对外部 API 的创建请求。提交时,会出现一个带进度条的阶段值,而不是“提交”按钮。创建过程在外部 API 上需要时间,因此我不得不使用 while status == 'inactive'
每秒 运行 几个显示请求,并在显示请求响应具有 status: 'active'
时停止。
每个 Show 请求响应还包含一个 'stage'
属性,它显示创建过程的阶段(连接、创建、获取、完成等)。对于每个请求,当前阶段都存储在@stage 变量中,可以使用 ApiRequest.stage
访问该变量。每个 API 相关的东西都在服务文件中。
我用阶段+进度条更改提交按钮的coffeescript:
$('#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
如何在每次值实时更改时将 #stage
中的文本更新为 ApiRequest.status
,保持在同一页面上,从提交表单的那一刻到结束(它无论如何都会在后台完成所有工作后重定向到 create.html?
要实时或至少接近实时显示您的操作状态,您必须
- 定期轮询服务器以查看状态是否已更改 - 也就是说,每隔一两秒持续点击
show
端点并在成功回调中更新状态标签
- 或者您可以实施一种方案,让服务器在状态发生变化时使用 WebSocket、长轮询或其他技术通知页面。
轮询就像你在开车,而你的一位乘客每秒都在问 "are we there yet?"。它不是很有效,特别是如果操作需要很长时间,因为每 n 秒发出一个单独的 HTTP 请求,只会返回 "still in progress" 响应。但它很容易实现,所以如果 show
动作很快并且操作本身相当快地完成,那么它可以是一个很好的折衷方案。
另一种方法是让服务器在状态发生变化时通知您。为此,您需要有一个发布者-订阅者基础设施。如果您使用 Rails 5,Action Cable is probably your best option as it is built right into Rails. You can find a detailed comparison of the different available technologies here: In what situations would AJAX long/short polling be preferred over HTML5 WebSockets?
如果您使用的是轮询,则可以将 success
常规 AJAX 调用的回调中的状态标签更新为 show
。如果 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 函数中。
我有一个基本表单,提交后会触发对外部 API 的创建请求。提交时,会出现一个带进度条的阶段值,而不是“提交”按钮。创建过程在外部 API 上需要时间,因此我不得不使用 while status == 'inactive'
每秒 运行 几个显示请求,并在显示请求响应具有 status: 'active'
时停止。
每个 Show 请求响应还包含一个 'stage'
属性,它显示创建过程的阶段(连接、创建、获取、完成等)。对于每个请求,当前阶段都存储在@stage 变量中,可以使用 ApiRequest.stage
访问该变量。每个 API 相关的东西都在服务文件中。
我用阶段+进度条更改提交按钮的coffeescript:
$('#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
如何在每次值实时更改时将 #stage
中的文本更新为 ApiRequest.status
,保持在同一页面上,从提交表单的那一刻到结束(它无论如何都会在后台完成所有工作后重定向到 create.html?
要实时或至少接近实时显示您的操作状态,您必须
- 定期轮询服务器以查看状态是否已更改 - 也就是说,每隔一两秒持续点击
show
端点并在成功回调中更新状态标签 - 或者您可以实施一种方案,让服务器在状态发生变化时使用 WebSocket、长轮询或其他技术通知页面。
轮询就像你在开车,而你的一位乘客每秒都在问 "are we there yet?"。它不是很有效,特别是如果操作需要很长时间,因为每 n 秒发出一个单独的 HTTP 请求,只会返回 "still in progress" 响应。但它很容易实现,所以如果 show
动作很快并且操作本身相当快地完成,那么它可以是一个很好的折衷方案。
另一种方法是让服务器在状态发生变化时通知您。为此,您需要有一个发布者-订阅者基础设施。如果您使用 Rails 5,Action Cable is probably your best option as it is built right into Rails. You can find a detailed comparison of the different available technologies here: In what situations would AJAX long/short polling be preferred over HTML5 WebSockets?
如果您使用的是轮询,则可以将 success
常规 AJAX 调用的回调中的状态标签更新为 show
。如果 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 函数中。