4

特定の機能のストリーミングアップデートで強化したいSinatraWebアプリがあります。ただし、現在は、これまでに行ったことのないストリーミングデータの使用方法を学習しようとしています。私は次の簡単なテストコードを持っています:

シナトラでは:

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

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>

これが私が望むことをしないことは驚くことではありません。つまり、書き込まれるときに各「foo」を取得し、ページを動的に更新します。代わりに、約10秒間何も起こらず、その後はfoo foo foo foo foo foo foo foo foo foo foo

私の質問は、ERBテンプレート(Ruby、jQuery、またはその他の手段を使用)で、すべてが収集されるまでブロックして一度に吐き出すのではなく、提供されたとおりにストリーミングデータをプルするにはどうすればよいですか?

4

2 に答える 2

5

Sinatra アクションは、HTTP 応答サイクル全体をラップします。つまり、要求を閉じる前に、アクションが終了するまで待機します。この時点で、ブラウザはデータが「完全」であり、「使用可能」であると見なします。上記のコードで作成したのは、非常に遅い Sinatra アクションだけです。

あなたが探しているテクノロジーは Websocket です。これは最新のブラウザーのほとんどでサポートされており、各クライアントとサーバー間の双方向通信チャネルを提供します。Websocket チャネルは、通常の HTTP 要求を「アップグレード」することによって作成されます。クライアントが Web ソケットをサポートしていない場合は、HTTP ロング ポーリングなどの手法を使用してエミュレートできます (データが利用可能になるまで、応答なしで要求が開かれたままになります。その時点で、データは応答チャネルに送られます。応答チャネルは閉じられ、クライアントはそれ以上のデータを取得するために新しい要求を開くことが期待されます)。

EventMachine とEM-Websocketを使用して、Ruby アプリでこの設定を行うことができます。代替手段は、JavaScript クライアントと Ruby サーバーを提供すると思われるSockyです。

于 2012-06-05T19:06:28.680 に答える
0

Sinatra でストリームを使用すると、通常のテンプレートはスキップされ、ストリーミングしている html のみを含む空白のページが表示されます。テキストとともにレイアウトを手動で作成してストリーミングすることで、これを回避できます。ここに例があります。

require 'sinatra'
require "sinatra/streaming"
set server: 'thin', connections: []

get '/' do
  stream do |out|
    settings.connections << out
    @out = out
    erb :stream
    out.callback { settings.connections.delete(out) }
  end
end
__END__
@@pre
  <!DOCTYPE html>
  <html>
  <head>
    <title>test</title>
  </head>
  <body>
   <h1>This is the body</h1>

@@after
  </body>
  </html>

@@stream
  <%
    @out.puts erb(:pre)
    @out.puts "<h2>test</h2>"
    (1..10).each do |i|
        @out.puts "#{i}<br>"
        sleep 2
      end
    @out.puts erb(:after)
    @out.flush
  %>
于 2017-02-08T14:26:25.497 に答える