2011-02-11 3 views
3

자바 스크립트에서 긴 폴링 요청을 시작하고 자바 스크립트에 여러 본문 섹션을 스트리밍하도록 루비 프로그램을 기대합니다. 왜 다음 (pseudo) 코드가 작동하지 않습니까? async sinatra를 사용하여 스트림 다중 본문

require 'rubygems' 
require 'sinatra/async' 
require 'eventmachine' 
require 'thin' 
require 'json' 

    class Test < Sinatra:Base 
     register Sinatra::Async 

     aget '/process' do 
     for c in 1..10 
      body { 
      { :data => [ "this is part #{c}" ] }.to_json 
      end 
     end 
     end 

     run! 
    end 

아마 내가 오래 무엇 폴링 및 비동기 수행하도록되어 오해하지만 내 기대는 내가 클라이언트로 다시 전송 여러 기관을 얻을 수 있다는 것입니다? 이벤트 머신 등을 사용해야합니까? 그것은 그 아래 example에 나타납니다

감사

+0

내가 너무 지금이 일하고 있어요. 내가 이해하는 것으로부터, 시체는 요청 작성 스트림을 닫고 전송합니다. 'body '를 연속으로 두 번 호출하면 페이지에서'asdf '만 볼 수 있습니다. 대신 write 나 response.write를 사용하도록 제안한 단서를 찾았습니다. 내 연결이 여전히 브라우저에서 열려있는 것을 볼 수있는 것처럼 보인다. 이 문제는 다시 한 행에 두 개의 write 호출이 예상대로 작동하지 않는다는 것을 의미합니다. –

+0

** 진부한 정보 ** : A)이 접근법이 실현 가능하지 않은 이유를 설명 할 수있는 사람에게 현상금을 수여합니다 (즉, 내가 생각하는 일부 HTTP 사양 때문). B) 몸에 쓸 코드를 브라우저에 표시 한 다음 2 초 후 몸에 쓰고이 업데이트를 브라우저에 표시하십시오. 누군가가 당신의 대답을 만져서 현상금 보상을 받기를 원하지 않는 한, 참조 또는 작업 코드를 제공하십시오. –

+0

지연된 응답에 대해 유감스럽게 생각합니다. 그러나 나는이 일을 다시 시작했습니다 (1.5 년 후). 예를 들어 웹 페이지를 통해 트리거 된 FTP 작업을 수행하는 경우를 예로들 수 있습니다. 이 웹 페이지에서 나는 기본적으로 실시간으로 업로드 된 바이트를 검색하려고했습니다. 명령 행에 출력을 표시하는 netftp를 사용하는 예제가 많이 있습니다. 하지만 귀하의 코드가 웹 페이지를 통해 어떻게 이루어질 수 있는지 보여줍니다. 나는 또한 Sinatra와 반대로 Ramaze를 통해 그것을하고 싶다. – gurpal2000

답변

6
require 'rubygems' 
require 'sinatra/async' 
require 'thin' 
require 'json' 

class Test < Sinatra::Base 
    register Sinatra::Async 

    class JSONStream 
    include EventMachine::Deferrable 

    def stream(object) 
     @block.call object.to_json + "\n" 
    end 

    def each(&block) 
     @block = block 
    end 
    end 

    aget '/process' do 
    puts 'ok' 
    out = JSONStream.new 
    body out 
    EM.next_tick do 
     c = 0 
     timer = EM.add_periodic_timer(0.3) do 
     c += 1 
     out.stream :data => ["this is part #{c}"] 
     if c == 100 
      timer.cancel 
      out.succeed 
     end 
     end 
    end 
    end 

    run! 
end 

참조 : http://confreaks.net/videos/564-scotlandruby2011-real-time-rack

+0

아직 진행 중이지만이 코드는 스트리밍. ** 빠른 응답을 주신 것에 대해 ** 감사합니다. (그리고이 말을 할 때, 나는 지금까지 당신이 당신이라는 것을 깨닫지 못했습니다.) (StackOverflow를 사용하려면 현상금을 수여하기까지 6 시간 정도 더 기다려야합니다.) –

+0

그런데이 절차에 대한 설명서를 작성하여 다른 사람들이이 과정을 이해하는 데 많은 시간을 할애하지 않아도됩니다. 나는 또한 유용한 정보를 배울 것이라고 확신한다. HTTP 스트리밍 문서를 어디에 둘 것인지 또는 추가 할 프로젝트에 대한 권장 사항이 있습니까? –

+1

나는 그렇지 않습니다. Rack에서 공식적으로 지원하지는 않기 때문에 async_sinatra, async-rack 프로젝트 (해킹 이상), thin 또는 well, dunno ...의 비동기 확장을위한 일종의 스펙이 좋을 것입니다. 또한 다른 서버에 쉽게 구현할 수 있습니다. –

1

당신은 여러 기관의 전송을 트리거하는 EventMachine 이벤트가 필요합니다. 이 이전의 answer도 참조하십시오. 또한

require 'sinatra/async' 

class AsyncTest < Sinatra::Base 
    register Sinatra::Async 

    aget '/' do 
    body "hello async" 
    end 

    aget '/delay/:n' do |n| 
    EM.add_timer(n.to_i) { body { "delayed for #{n} seconds" } } 
    end 

end 
+1

죄송합니다.하지만 여러 명의 시신을 어떻게 보냅니 까? 이것은 단지 지연된 비동기 응답을 보냅니 까? – gurpal2000

+0

내가 알 수있는 것으로부터, 이것은 n 초 지연된 하나의 시체를 보냅니다. gurpal이 하나의 요청에 대해 여러 본문을 보내거나 하나의 본문을 전송하려고하지만 스트리밍 방식으로 새로운 데이터가 들어올 때 업데이트되도록하려는 경우 약간의 혼동이있을 수 있습니다. –