我有一个运行几分钟的Ruby命令行应用程序。在执行期间,在应用程序的每个阶段完成后,我会向命令行输出打印几条消息。
这只是为了让用户知道应用程序运行的阶段,并使应用程序提供更多信息。
现在,我想将应用程序移植到Sinatra应用程序。我已经准备好了整个框架。我正在使用jQuery AJAX将输出结果打印回用户。
问题是,它只在整个应用程序运行后呈现输出,因此使其不具有反应性(与命令行应用程序相比)。在某些情况下,整个应用程序运行甚至可能需要2-3分钟,然后将结果打印到网页上。
这相当于做一个POST,我在这里没有从jQuery AJAX调用中获得任何东西。 有没有办法可以将我打印到STDOUT的相同消息发送回网页上的用户。
这可能是一个非常简单的问题,但我是新手,并且在过去做过类似的事情。
如果您需要更多信息,请与我们联系。
答案 0 :(得分:3)
你所说的是执行的状态。有几种方法可以解决它,使用服务器发送事件(SSE),使用websockets或只是轮询更改。
最简单的解决方案是轮询变更。有另一个Ajax方法每隔一段时间向网站发送一个请求,服务器将返回具有长时间运行进程当前状态的响应。
在长时间运行的过程中需要具备的是里程碑,您可以更新状态并且可以为其他人访问它,即某种数据库(Redis,Memcached,SQL-ish)或线程但是这不能很好地扩展。
答案 1 :(得分:2)
一段时间后我遇到了类似的问题,我采取了更聪明的问题。通过它的方式。我做的是,我添加了一个JavaScript代码片段,当ruby程序在后台运行时,它将继续在网页上加载新文本。 JavaScript代码将在完成该过程时停止运行。通过这种方式,您的应用程序将成为“响应式”#34;并会节省你很多时间。
执行上述操作的逐步方法应如下(据我所知):
在您的ruby代码中添加一个标志,当您的处理完成时,该标志应该转为true(取决于您的代码究竟是什么)。
添加一些javascript代码。像这样:
$(document).ready(function() {
$('#demo1').click(function() {
$.blockUI({ message: $('#loginForm') });
setTimeout($.unblockUI, 2000);
});
});
答案 2 :(得分:2)
我使用sinatra应用程序执行类似的操作,该应用程序运行我的规范并在浏览器中显示当前的构建状态。
有三件事情可以解决这个问题:
Thread.new
然后,我的javascript间隔函数向app传递构建id发出ajax请求,并返回logs数组(因此,不断扩充直到构建结束)。
这是一个抽象的例子:
require 'sinatra'
require 'json'
Thread.abort_on_exception = true
Logs = []
post '/build' do
Logs.clear
Thread.new do
my_cmd = IO.popen( "my_long_running_binary 2>&1" )
Logs.push( line ) while ( line = my_cmd.gets )
my_cmd.close
end
200
end
get '/build.json' do
JSON.dump Logs
end