Іноді потрібно почати відправляти дані клієнту прямо в процесі генерування частин цих даних. В особливих випадках потрібно постійно відправляти дані до тих пір, поки клієнт не закриє з'єднання. Ви можете використовувати метод stream замість написання власних "обгорток".
Почнемо з класичного прикладу з документації Sinatra:
get '/' do
stream do |out|
out << "It's gonna be legen -\n"
sleep 0.5
out << " (wait for it) \n"
sleep 1
out << "- dary!\n"
end
end
Якщо сервер не підтримує стрімінг (наприклад, WEBRick), то всі дані будуть відправлені за один раз відразу після того, як блок, переданий в stream, завершиться.
Це дозволяє вам реалізувати потокові API, Server-Sent Events, і може служити основою для WebSockets. Також такий підхід можна використовувати для збільшення продуктивності у випадку, коли якась частина контенту залежить від повільного ресурсу.
І що дійсно цікаво: якщо ви працюєте на потоковому(evented) сервері, наприклад Thin, ви можете тримати з'єднання відкритим і легко реалізувати обмін повідомленнями.
Якщо метод stream використовується з параметром keep_open, то він не буде викликати close в об'єкта потоку, що дозволить вам закрити його пізніше в будь-якому іншому місці.
Приклад простого чату:
https://gist.github.com/2551354
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- encoding: utf-8 -*- | |
require 'sinatra' | |
require 'slim' | |
set :server, 'thin' | |
connections = [] | |
get '/' do | |
halt slim(:login) unless params[:user] | |
slim :chat, :locals => { :user => params[:user].gsub(/\W/, '') } | |
end | |
get '/stream', :provides => 'text/event-stream' do | |
stream :keep_open do |out| | |
connections << out | |
out.callback { connections.delete(out) } | |
end | |
end | |
post '/' do | |
connections.each { |out| out << "data: #{params[:msg]}\n\n" } | |
# http://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP#204 | |
204 # response without entity body | |
end | |
__END__ | |
@@ layout | |
html | |
head | |
title Simple Chat with Sinatra | |
meta charset="utf-8" | |
script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" | |
body | |
== yield | |
@@ login | |
form action='/' | |
label for='user' User Name: | |
input name='user' value='' | |
input type='submit' value="GO!" | |
@@ chat | |
form | |
input id='msg' placeholder='type message here...' | |
pre id='chat' | |
javascript: | |
// reading | |
var es = new EventSource('/stream'); | |
es.onmessage = function(e) { $('#chat').append(e.data + "\n") }; | |
// writing | |
$("form").live("submit", function(e) { | |
$.post('/', {msg: "#{user}: " + $('#msg').val()}); | |
$('#msg').val(''); $('#msg').focus(); | |
e.preventDefault(); | |
}); |
Немає коментарів:
Дописати коментар