与Sinatra一起流,逐渐更新目的地

asf*_*ows 4 javascript sinatra

我有一个Sinatra网络应用程序,我非常希望通过某些功能的流更新来增强.但是现在,我只是想学习使用流媒体数据的方法,这是我以前从未做过的.我有以下简单的测试代码:

在Sinatra:

get '/foo' do
  stream do |out|
    10.times do
      out.puts "foo"
      out.flush
      sleep 1
    end
  end
end

get '/bar' do
  erb :bar
end
Run Code Online (Sandbox Code Playgroud)

bar.erb:

<body>
  <div class="stream">
    nothing.
  </div>
</body>

<script type="text/javascript" charset="utf-8">
  $(document).ready( function() {
    $.get('/foo', function(html) {
      $(".stream").html(html);
    });
  });
</script>
Run Code Online (Sandbox Code Playgroud)

我并不感到惊讶,这不是我想做的,也就是在写入时每个'foo'并动态更新页面.相反,没有任何事情发生约10秒然后我得到foo foo foo foo foo foo foo foo foo foo foo.

我的问题是,如何在ERB模板(使用Ruby,jQuery或其他方法)中提取流式数据,而不是阻塞,直到它全部被收集并立即全部吐出?

小智 5

Sinatra操作包装整个HTTP响应周期 - 这意味着它会在关闭请求之前等待操作完成,此时浏览器会认为数据"完整"且"正常"可供使用.您在上面的代码中创建的所有内容都是非常非常慢的Sinatra操作.

您正在寻找的技术是Websockets,它受大多数现代浏览器的支持,并在每个客户端和服务器之间提供双向通信通道.websocket通道是通过"升级"常规HTTP请求来创建的.在客户端不支持Web套接字的情况下,可以使用诸如HTTP Long Polling(其中请求保持打开,没有响应,直到有可用数据)等技术来模拟它们,此时数据被分流到响应通道,响应通道关闭,客户端需要打开一个新请求以获取任何进一步的数据.

您可以使用EventMachine和EM-Websocket在Ruby应用程序中设置此设置.另一个是Socky,我认为它提供了javascript客户端以及Ruby服务器.

  • 请注意,Erb或Haml不以任何流式方式提供内容,因此Sinatra无法传输来自它们的任何响应.但是,Sinatra*可以*自己发送流媒体响应,*iff*您有流媒体内容来提供它. (2认同)