модуль ActionController::Streaming
Контроллер действий Streaming
Позволяет передавать представления клиенту по мере их отображения.
По умолчанию Rails отображает представления, сначала отображая шаблон, а затем макет. Ответ отправляется клиенту после отображения всего шаблона, выполнения всех запросов и обработки макета.
Streaming меняет порядок отображения: сначала отображается макет, а затем каждая его часть по мере обработки. Благодаря этому заголовок HTML (обычно расположенный в макете) можно быстро передать клиенту, что позволяет загружать JavaScript и таблицы стилей раньше обычного.
Некоторые промежуточные компоненты Rack могут работать некорректно, поэтому при потоковой передаче следует соблюдать осторожность. Подробнее об этом рассказано ниже, в разделе «Промежуточные компоненты в Streaming».
Streaming можно легко добавить к определённому шаблону: достаточно передать параметр :stream в render.
class PostsController
def index
@posts = Post.all
render stream: true
end
end
Когда использовать потоковую передачу
Streaming может быть избыточной для простых действий, таких как new или edit. Потоковая передача приносит реальную пользу при выполнении ресурсоёмких действий, например тех, которые выполняют множество запросов к базе данных.
В таких действиях запросы следует выполнять как можно позже. Например, рассмотрим следующее действие 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 работает только с шаблонами. Rendering :json или :xml с :stream работать не будут.
Обмен данными между макетом и шаблоном
При потоковой передаче отображение идёт сверху вниз, а не изнутри наружу. Rails начинает с макета, а шаблон отображается позже, когда доходит очередь до его yield.
Это означает, что переменные экземпляра, заданные в шаблоне и используемые в макете, перестанут работать после перехода на потоковую передачу. Правильный способ обмена данными между макетом и шаблоном — независимо от того, используется потоковая передача или нет — это content_for, provide и yield.
Рассмотрим простой пример: макет ожидает, что шаблон укажет заголовок, который следует использовать:
<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>
При этом при потоковой передаче нужно тщательно проверять шаблоны и выбирать, когда использовать provide, а когда — content_for.
Подробнее см. также в разделе ActionView::Helpers::CaptureHelper.
Заголовки, файлы cookie, сессия и flash
При потоковой передаче HTTP-заголовки отправляются клиенту непосредственно перед отображением первой строки. Это означает, что изменения заголовков, файлов cookie, сессии или flash после начала отображения шаблона не будут переданы клиенту.
Промежуточные компоненты
Промежуточные компоненты, которым необходимо изменять тело ответа, не будут работать при потоковой передаче. Отключайте их при потоковой передаче в среде разработки или эксплуатации. Например, Rack::Bug не будет работать при потоковой передаче, поскольку ему необходимо вставлять содержимое в тело HTML.
Кроме того, Rack::Cache не будет работать при потоковой передаче, поскольку пока не поддерживает потоковые тела ответа. При потоковой передаче Cache-Control автоматически устанавливается в значение «no-cache».
Ошибки
При потоковой передаче обработка исключений становится немного сложнее. Это связано с тем, что часть шаблона уже отображена и передана клиенту, поэтому отобразить страницу с исключением целиком невозможно.
В настоящее время при возникновении исключения в среде разработки или эксплуатации Rails автоматически передаёт клиенту:
"><script>window.location = "/500.html"</script></html>
Первые два символа (">) нужны на случай, если исключение возникнет при отображении атрибутов определённого тега. Причину исключения можно найти в журнале.
Поддержка веб-серверами
Все серверы, совместимые с Rack 3+, поддерживают потоковую передачу.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.