跳到內容 跳到搜尋

動作控制器 Streaming

允許在畫面呈現時,將畫面串流傳回至用戶端。

預設Rails畫面會先呈現樣板,然後再呈現版面配置。當完整的樣板被呈現,所有的查詢都做完,與版面配置被處理完後,回覆才會傳送至用戶端。

Streaming會先呈現版面配置,然後在處理的同時,陸續呈現版面配置的每個部分,這會讓 HTML 的標題 (通常在版面配置中) 可以很快的串流回傳到用戶端,讓 JavaScript 和樣式表比平常更早載入。

某些 Rack 中間件可能無法工作,所以在使用串流時請多加注意。以下內容有更詳細的說明,請參閱 Streaming 中的中間件 章節。

Streaming 可以輕易加入既有的樣板,唯一要做的事就是傳遞 :stream 選項給 render

class PostsController
  def index
    @posts = Post.all
    render stream: true
  end
end

串流適用的時機

Streaming 可能被視為用在類似 newedit 等簡單動作時會有矯枉過正之嫌。串流真正的優勢在於處理耗費時間的動作,例如對資料庫執行大量的查詢。

在這些動作中,您可能會想要盡量延後查詢的執行時間。例如,想像有以下的 dashboard 動作

def dashboard
  @posts = Post.all
  @pages = Page.all
  @articles = Article.all
end

大部分的查詢在此是在控制器中發生的。為了受惠於串流,您會想要將其改寫成

def dashboard
  # Allow lazy execution of the queries
  @posts = Post.all
  @pages = Page.all
  @articles = Article.all
  render stream: true
end

請注意 :stream 僅適用於樣板。使用 :stream呈現 :json:xml 將無法作用。

版面配置與樣板間的溝通

在執行串流時,畫面呈現是由上而下的,而非由內而外。 Rails 會從版面配置開始,樣板則會在稍後,到達其 yield 時才會被呈現。

這表示,如果您的應用程式目前依賴樣板中設定的實例變數在版面配置中使用,當您轉換到串流時,它們將無法運作。在版面配置與樣板間進行溝通的正確做法 (不論是否使用串流) 是使用 content_forprovideyield

以下是一個簡單的範例,版面配置期望樣板告訴它要使用哪個標題

<html>
  <head><title><%= yield :title %></title></head>
  <body><%= yield %></body>
</html>

您可以在樣板中使用 content_for 來指定標題

<%= content_for :title, "Main" %>
Hello

最後的結果會是

<html>
  <head><title>Main</title></head>
  <body>Hello</body>
</html>

然而,如果 content_for 被呼叫多次,最後的結果將會是所有的呼叫串接在一起。舉例來說,如果我們有以下的樣板:

<%= content_for :title, "Main" %>
Hello
<%= content_for :title, " page" %>

最後的結果會是

<html>
  <head><title>Main page</title></head>
  <body>Hello</body>
</html>

這表示若您的版面配置中有 yield :title,而您又想要使用串流,您必須在串流標題與所有資源以前呈現整個樣板 (而最終觸發所有的查詢),這違背了串流的宗旨。另一種做法是使用一個名為 provide 的輔助程式,其功能與 content_for 相同,但會告知版面配置停止搜尋其他條目並繼續呈現。

例如,使用 provide 的範例範本如下:

<%= provide :title, "Main" %>
Hello
<%= content_for :title, " page" %>

最後的呈現結果為:

<html>
  <head><title>Main</title></head>
  <body>Hello</body>
</html>

換句話說,在進行串流時,您需要適當地檢查範本並選擇使用 providecontent_for

詳情請參閱 ActionView::Helpers::CaptureHelper

標頭、Cookie、階段和簡訊

在串流播放時,HTTP 標頭會在呈現第一行之前傳送給用戶端。這表示在範本開始呈現之後修改標頭、Cookie、階段或簡訊,將不會傳播至用戶端。

中介軟體

需要處理本體中介軟體無法使用串流播放。在開發或製作中串流播放時,您應停用這些中介軟體。例如,Rack::Bug 在串流播放時無法使用,因為它需要將內容插入 HTML 本體。

此外,Rack::Cache 也無法與串流播放配合使用,因為它還不支援串流播放本體。在串流播放 Cache-Control 時,會自動設定為「no-cache」。

錯誤

在串流播放方面,例外情況會複雜一點。會發生這種情況是因為範本的部分已呈現並串流播放至用戶端,因此無法呈現整個例外情況頁面。

目前,當在開發或製作時發生例外情況,Rails 將自動串流至用戶端

"><script>window.location = "/500.html"</script></html>

在為特定標籤呈現屬性時發生例外情況,則需要頭兩個字元 (">)。您可以在記錄器中查看例外情況的真正原因。

Web 伺服器支援

所有相容於 Rack 3+ 的伺服器都支援串流播放。