Created
November 27, 2017 03:34
-
-
Save akirattii/87f58f9192c5e39efb99e4422f465a6b to your computer and use it in GitHub Desktop.
Example: Server-Sent Event (SSE) + expressjs
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
/* | |
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