【发布时间】:2011-12-23 23:26:35
【问题描述】:
我想使用 Sinatra 在 1.3 中引入的 Streaming 功能以及一些标准输出重定向。它基本上是一个长期运行的工作的实时流输出。我查看了自述文件中的this question 和 Sinatra 流式传输示例。
在 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 在第一次调用时是空的,它永远不会输出到输出缓冲区。我不太确定正确的顺序是什么,如果有任何建议,我将不胜感激。
我尝试了上面问题中提到的一些 EventMachine 实现,但无法让它们工作。
更新
我尝试了一些与我在新线程中运行该方法的位置略有不同的方法,并按照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 没有流媒体功能吗?
【问题讨论】:
标签: ruby streaming sinatra redirect stdout