Eventos enviados pelo servidor

Resumo: os eventos enviados pelo servidor são uma maneira simples de enviar dados do servidor para um aplicativo de navegador em um navegador da Web moderno (ou seja, não o IE).

Se você deseja enviar dados do servidor para um navegador moderno, uma alternativa mais simples para WebSockets e socket.io que é integrado ao Chrome, Safari e Firefox são os eventos do lado do servidor . Ele não permitirá que os clientes façam push de volta, mas você pode usar HTTP POSTs padrão para isso.

Há um ótimo artigo sobre isso no site HTML5 Rocks do Google: http://www.html5rocks.com/en/tutorials/eventsource/basics/

O SSE usa um formato simples baseado em texto para troca de dados e fornece a interface de ouvinte de evento familiar no navegador. Os exemplos de código estão no CoffeeScript porque é incrível. 🙂

# Listen to the '/listen' route on the server
source
= new EventSource '/listen'
source
.addEventListener 'textMessage', (e) ->
$
('BODY').append "<DIV>#{e.data}</DIV>"
, false

O retorno de chamada é disparado com um objeto de evento que contém a carga útil do evento (e.data), bem como um id de evento se você precisar rastreá-lo. Você também pode enviar uma string JSON como os dados.

A implementação do lado do servidor não requer nada complicado. Ele apenas mantém o soquete de solicitação aberto e grava cada dado em um formato de texto simples. Os eventos são delimitados por dois caracteres de nova linha. Então, aqui está um exemplo de como os dados do evento podem ser exibidos durante a transmissão, se você estiver enviando haicais para o cliente:

id: 1001
event: haikuText
data
: server pushed events?
data
: forget about WebSockets
data
: SSE's easy

id: 1002

data: writing tech blog post

data: need compelling examples

data: don'
t write a haiku

id
: 1003
...

Aqui, há três eventos (com o terceiro truncado), cada um separado por duas novas linhas. Simples.

No momento em que este artigo foi escrito, não parecia que o Web Inspector mostraria esse tráfego (o corpo da resposta está sempre em branco), então isso pode ser surpreendente quando você inspecionar.

E para fins de integridade, aqui está uma implementação de servidor rápida e suja em Node.js:

http = require 'http'
events
= require 'events'
fs
= require 'fs'

lastId
= 0
emitter
= new events.EventEmitter()
server
= http.createServer (request, response) ->
if request.url is '/' then return indexRoute request, response
if request.url is '/listen' then return listenRoute request, response
if request.url is '/speak' then return speakRoute request, response
response
.writeHead 404
response
.end 'not found'

# You can imagine how HTML file this look, a textbox and
# a listener to the server EventSource.
indexRoute
= (request, response) ->
html
= fs.readFileSync './sse.html'
response
.end html

speakRoute
= (request, response) ->
console
.log '/speak'
buffer
= []
request
.on 'data', (d) ->
buffer
.push d.toString()
request
.on 'end', ->
event = serverEvent ++lastId, 'text', JSON.parse(buffer.join '')
emitter
.emit 'text', event
response
.writeHead 202
response
.end 'Received text message.'

# Make a server-side event string
serverEvent
= (id, event, data) ->
"event: #{event}n" +
"id: #{id}n" +
"data: #{JSON.stringify data}nn"

listenRoute
= (request, response) ->
console
.log '/listen'
request
.socket.setTimeout Infinity
response
.writeHead 200,
'Content-Type': 'text/event-stream'
'Cache-Control': 'no-cache'
'Connection': 'keep-alive'
response
.write 'n'
response
.on 'close', ->
emitter
.removeListener 'text', response.write
console
.log 'closed!'

emitter
.on 'text', (event) ->
console
.log 'sending data!'
console
.log event
response
.write event

server
.listen 4444
console
.log 'Up!'