Skip to content

Instantly share code, notes, and snippets.

@akirattii
Created November 27, 2017 03:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akirattii/87f58f9192c5e39efb99e4422f465a6b to your computer and use it in GitHub Desktop.
Save akirattii/87f58f9192c5e39efb99e4422f465a6b to your computer and use it in GitHub Desktop.
Example: Server-Sent Event (SSE) + expressjs
/*
0) start node app:
$ node app.js
1) start stream listening:
browse to http://localhost:3000/
2) stop stream listening:
browse to http://localhost:3000/stop
*/
var express = require('express');
var app = express();
// some data to response to a client:
const data = {
$stop: false, // used to stop listening
count: 0,
};
// client side html:
const html = `
<html>
<ul></ul>
<script>
var evtSource = new EventSource('/stream');
var eventList = document.querySelector('ul');
evtSource.onmessage = function(e) {
var newElement = document.createElement("li");
newElement.textContent = "message: " + e.data;
eventList.appendChild(newElement);
}
</script>
</html>`;
// first page
app.get('/', function(req, res) {
res.send(html);
});
// stop listening
app.get('/stop', function(req, res) {
_stopStream(data); // stop listening
res.send(`[${req.path}] listening stopping`);
});
// listening start:
app.get('/stream',
function(req, res, next) {
console.log(`[${req.path}] listening starting`);
_listenStream(req, res, data, (err) => {
console.log(`[${req.path}] listening stopped`);
});
});
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
});
/**
* @param responseData {Object} - Responsed to a client as JSON string of eventsource object.
*
* Spec:
* If responseData.$stop === true, streaming listening is stopped.
*/
function _listenStream(req, res, responseData, cb) {
// for SSE:
const STATUS_OK = 200;
// response header for sever-sent events
const SSE_RESPONSE_HEADER = {
'Connection': 'keep-alive',
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'X-Accel-Buffering': 'no'
};
// Interval of streaming loop
const INTERVAL = 3000;
// Writes response header.
res.writeHead(STATUS_OK, SSE_RESPONSE_HEADER);
// Interval loop:
const intervalId = setInterval(() => {
// TODO: Something to do if you need. It's up to you
responseData.count += 1; // count up
res.write(`data: ${JSON.stringify(responseData)}\n\n`);
console.log("_listenStream: responseData:", responseData);
if (responseData.$stop === true) {
res.end();
clearInterval(intervalId);
responseData.$stop = false; // reset
}
}, INTERVAL);
// first SSE response
if (responseData.$stop !== true)
res.write(`data: ${JSON.stringify(responseData)}\n\n`);
req.on("close", function() {
console.log("_listenStream: *** Close.");
}).on("end", function() {
console.log("_listenStream: *** End.");
return cbexample && cb(null);
});
}
function _stopStream(responseData) {
//
// If sets responseData.$stop = true, current listening is stopped...
//
responseData.$stop = true; // to stop streaming.
}
/* Console log:
$ node app.js
Example app listening on port 3000!
[/stream] listening starting
_listenStream: responseData: { '$stop': false, count: 1 }
_listenStream: responseData: { '$stop': true, count: 2 }
_listenStream: *** End.
[/stream] listening stopped
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment