我想使用Sinatra在1.3中引入的Streaming功能以及一些stdout重定向。它基本上是长时间运行作业的直播输出。我在README中查看了this question和Sinatra streaming样本。Sinatra 1.3 Streaming with Ruby stdout重定向
OSX上运行1.8.7:
require 'stringio'
require 'sinatra'
$stdout.sync = true
module Kernel
def capture_stdout
out = StringIO.new
$stdout = out
yield out
ensure
$stdout = STDOUT
end
end
get '/' do
stream do |out|
out << "Part one of a three part series... <br>\n"
sleep 1
out << "...part two... <br>\n"
sleep 1
out << "...and now the conclusion...\n"
Kernel.capture_stdout do |stream|
Thread.new do
until (line = stream.gets).nil? do
out << line
end
end
method_that_prints_text
end
end
end
def method_that_prints_text
puts "starting long running job..."
sleep 3
puts "almost there..."
sleep 3
puts "work complete!"
end
所以这段代码打印出前三串正常,并阻止而method_that_prints_text
执行,并不会打印出任何东西到浏览器。我的感觉是stdout在第一次调用时是空的,它从不输出到out缓冲区。我不太确定正确的顺序会是什么,并会感谢任何建议。
我尝试了上述问题中提到的一些EventMachine实现,但无法让它们工作。
UPDATE
我试过的东西,我必须在一个新线程的run方法略有不同,如描述here重载stdout该线程...
代替上述Kernel.capture_stdout
.. 。
s = StringIO.new
Thread.start do
Thread.current[:stdout] = s
method_that_prints_text
end.join
while line = s.gets do
out << line
end
out << s.string
有了上面的链接中列出的ThreadOut
模块,这似乎工作好一点。但它不流。唯一一次打印到浏览器上的是最后一行out << s.string
。 StringIO
没有流式传输功能吗?