2016-04-13 38 views
1

我最近發現鐵軌流,並具有閱讀各種文檔,我試着將它添加到我的控制器之一,像這樣:Rails的流:「渲染流:真正的」不工作

def index 
    render :stream => true 
end 

我的模板文件目前看起來像這樣:

<%10.times do%> 
    <p> 
    I should get streamed ERB... 
    <%sleep 0.5%> 
    </p> 
<%end%> 

但不是每0.5秒顯示一條消息,而是等待5秒鐘並顯示整個頁面!我在瀏覽器中檢查了這種行爲並使用了curl。

我使用OSX麒麟,是的,我配置unicorn.rb流媒體:

listen 3000, :tcp_nodelay => true, :tcp_nopush => false 
worker_processes 1 

如果你想看到我的佈局文件,它看起來像這樣:

<!DOCTYPE html> 
<html> 
<head> 
    <title>StreamingTest</title> 
    <%= stylesheet_link_tag "application" %> 
    <%= javascript_include_tag "application" %> 
    <%= csrf_meta_tags %> 
</head> 
<body> 

<%= yield %> 

</body> 
</html> 

我嘗試禁用所有的寶石(rai​​ls和postgres除外),並且將我的控制器,佈局和模板減少到最低限度,沒有任何成功。

我甚至去下載一個完整的流媒體演示,我發現(https://github.com/slim-template/slim-streamingtest),當我運行它,它也沒有流! (請注意任何人試圖運行該演示:我必須更改gemfile源使用https而不是http,然後才能「捆綁安裝」,並且在運行之前我必須「捆綁更新鏈接」)

I注意,別人(使用彪馬)似乎有類似的問題,還沒有得到圓滿解決:

Rails Streaming not Streaming

這可能是任何對我的作品也將會爲他們工作。

如果我能夠正常工作,流式傳輸對我們的應用程序確實有幫助,但我甚至無法獲得演示流式傳輸應用程序正常運行!我懷疑它可能與我的開發環境有關,但是當我將我的應用程序部署到Heroku時,問題依然存在,而且我沒有想法。任何幫助將不勝感激 。 。 。

謝謝!

+0

我從來沒有玩過它。但一旦搞清楚了,就嘗試在Action Cable上構建它。 – 7urkm3n

+0

您使用的是哪個版本的Rails? –

+0

Rails 4.1.8,ruby 2.1.2 – dacoinminster

回答

1

我試過你提到的演示回購,行爲如預期。在示例中,您將顯示它將停止流式傳輸模板,然後等待它在5秒後完全渲染,然後發送剩餘的部分。如果使用捲曲:

# curl -i http://localhost:3000 

HTTP/1.1 200 OK 
Date: Thu, 21 Apr 2016 17:29:00 GMT 
Connection: close 
Cache-Control: no-cache 
Transfer-Encoding: chunked 
Content-Type: text/html; charset=utf-8 
X-UA-Compatible: IE=Edge 
X-Runtime: 0.018132 

<!DOCTYPE html> 
<html> 
    <head> 
    <title>StreamingTest</title> 
    <link href="/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" /> 
    <script src="/javascripts/application.js" type="text/javascript"></script> 
    <meta content="authenticity_token" name="csrf-param" /> 

然後等待5秒讓模板完成其渲染併發送它。

... 
    <p> 
    I should get streamed... 
    </p> 
</body></html> 

這就是應該發生的事情。它不會每0.5秒發送一部分部分。

使用模板進行流式處理的主要目標是讓瀏覽器在內容的其餘部分之前接收標題,以便可以節省加載資源的時間。如所述in the docs

流處理通過先渲染布局並在處理佈局的每個部分時對其進行流式處理,從而顛倒渲染流。這使得HTML(通常在佈局中)的頭部可以非常快速地傳輸回客戶端,從而允許JavaScript和樣式表比平常更早加載。

除非已完全呈現,否則不會發送該部分。

但是,向你展示如何讓這種行爲你希望你可以改變的application.html.slim佈局這樣的身體:

body 
    = yield 
    = render 'application/other' 

並用以下內容創建一個名爲局部_other.html.erb

<% sleep 1 %> 
<p>Me too!</p> 

現在你會看到捲曲它呈現佈局的開始,等待渲染完成index.html.erb,發送它並顯示在捲曲中,然後等待_other.html.erb部分要完成渲染才能結束請求體。瞧。

你也可以直接喂請求主體,發送內容每隔幾毫秒,你可以做到以下幾點:

def index 
    headers['Cache-Control'] = 'no-cache' 
    self.response_body = Enumerator.new do |yielder| 
    10.times do 
     yielder << "I should be streamed...\n" 
     sleep 0.3 
    end 
    end 
end 

然而,這並不意味着發送HTML,但您可以通過使用render_to_string但隨後你將不得不在你的代碼中修改很多。

請注意,所有這些都是Rails 3.x,對於4.x,您必須使用ActionController::Live。在ActionController::Live的情況下,有一些示例說明如何在js中偵聽服務器發送的事件以呈現客戶端,如mini-chat

+0

非常感謝回答@ marc-lainez!我開始認爲我永遠不會得到答案,即使我附加了獎金! – dacoinminster

+0

我曾經希望我可以使用「render:stream => true」來阻止我的頁面超時(我使用的是Heroku,它不會讓我增加超時時間,並且頁面花了很長時間構建),但即使流式傳輸,頁面仍然超時。這聽起來像是預期的行爲?我通過優化頁面加載速度來解決這個問題,所以我不需要像我開始時那樣糟糕的答案,但是我會獎勵你賞金,因爲你真的花時間去幫助! – dacoinminster

+0

我瞭解你最終會遇到的情況,以及爲什麼你認爲使用流或服務器發送的事件來解決這個問題是一個好主意,但是我個人認爲這不是正確的方法。當你提取數據並渲染大部分內容時,你所描述的似乎是性能問題。第一步是將數據庫查詢優化到極限,然後使用緩存。另一種方法是使用AJAX請求獲取某些內容,而不是常規模板呈現。如果您在這些主題上發佈另一個問題,我很樂意提供幫助。最好。 –