我的rails应用程序中有一个ajax请求,该请求从我的 Controller 操作返回一个变量。在 Controller Action 内部,我有一个循环,可能需要一些时间才能完成。
Controller
def myAction
$j = 1
until $j > list_size do
array << { :foo => $j }
$j +=1;
end
@myvariable = array.to_json
end
myAction.js.erb
var myVariable = JSON.parse("<%= escape_javascript(raw @myvariable) %>");
for (var k = 0; k < myVariable.length; k++) {
$("#myDiv").append(myVariable[k].foo);
}
我希望能够在循环的每个阶段将结果呈现给js.erb部分,而不是等待循环完成。在不中断循环并在循环结束之前过早结束操作的情况下,这是否可能?也许像这样(错误的伪代码):
Controller
def myAction
$j = 1
until $j > list_size do
array << { :foo => $j }
render array.to_json
$j +=1;
end
end
myAction.js.erb
var myVariable = JSON.parse("<%= escape_javascript(raw @myvariable) %>");
$("#myDiv").append(myVariable.foo);
最佳答案
render stream: true
将延迟加载查询,并在呈现 Assets 和布局后允许它们运行。流仅适用于模板,不适用于任何其他形式(例如json或xml)。
因此,您不走运,您将不得不使用Rail 4及更高版本中可用的ActionController::Live
。 Live是ActionController类中包含的一个特殊模块。它使Rails可以显式打开和关闭流。这是经过修改的伪代码,使其更像 ruby ,并且避免了全局变量:
class MyController < ActionController::Base
include ActionController::Live
def action
(1..list_size).each do |list_item|
response.stream.write("{ "foo": #{list_item} }")
end
ensure
response.stream.close
end
end
上面的代码将从1循环到
list_size
,并立即将每个list_item 输出。若要使用此功能,则应使用服务器发送的事件。通常,网页必须询问是否有任何更新。使用服务器发送的事件,更新会自动出现。
请使用以下资源来了解有关流,SSE和事件源的更多信息: