Reputation: 3770
I was hoping to use SSE to dynamically send messages to the browser. Ideally I would like a minimal application where the browser does nothing until a function or method (which takes the message as it's argument) is called and the browser receives this message an logs it only once. I have tried to illustrate this with the below:
const http = require("http");
const server = http.createServer(<not sure what code goes here>);
server.listen(8000);
// this can be called at any time after creating the server so the browser
// can receive the message and log it to the console.
sendMessageToBrowser(`data: this is a dynamic message\n\n`)
However, the below basic SSE application below simply logs "hello world" to the browser console every 3 seconds (the default). I don't understand how this is any different to serving data via a regular route and using something like:
setInterval(fetch("/events").then(res => res.text()).then(data => console.log(data)));
Is my request possible with SSE or have I misunderstood how it works? I know my request is possible with websockets/socket.io but was hoping to use SSE as I don't want to use a library and SSE simpler to understand and implement.
Minimal example which logs hello world every 3 seconds:
const http = require("http");
const server = http.createServer((req, res) => {
// Server-sent events endpoint
if (req.url === "/events") {
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
res.end(`data: hello world\n\n`);
return;
}
// Client side logs message data to console
res.writeHead(200, { "Content-Type": "text/html" });
res.end(`
<script>
var eventSource = new EventSource('/events');
eventSource.onmessage = function(event) {
console.log(event.data);
};
</script>
`);
});
server.listen(8000);
Upvotes: 0
Views: 1814
Reputation: 3770
This is a minimal version of @Mattia's answer.
const http = require("http");
var resEvents;
const server = http.createServer((req, res) => {
if (req.url === "/events") {
resEvents = res;
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
return;
}
res.writeHead(200, { "Content-Type": "text/html" });
res.end(`
<script>
var eventSource = new EventSource('/events');
eventSource.onmessage = function(event) {
console.log(event.data);
};
</script>
`);
});
server.listen(8000);
// this can only be run after the browser has connected - either run code
// sequentially in a REPL or put this in a setTimeout() to give you time
// to go to localhost:8000
resEvents.write(`data: hello\n\n`);
Upvotes: 0
Reputation: 140
I don't know if I really understand what you need. I changed the code and now if you go to /sendEvent
url you see a new log in the root page.
You can use resEvents
var inside any function to log a new message in the root page.
const http = require("http");
var resEvents;
var count = 0;
var myInterval = setInterval(() => {
if (count < 50) sendMessageToBrowser(count);
else clearInterval(myInterval);
}, 1000);
function sendMessageToBrowser(msg) {
if (resEvents) {
resEvents.write(`data: ${msg}\n\n`);
count++;
}
}
const server = http.createServer((req, res) => {
// Server-sent events endpoint
if (req.url === "/events") {
resEvents = res;
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive"
});
res.write(
`data: Go to http://localhost:8000/sendEvent to log a new Messages \n\n`
);
return;
}
if (req.url === "/sendEvent") {
if (!resEvents) {
res.writeHead(200, { "Content-Type": "text/html" });
res.end(`Logged a new Message<br>Refresh the page to log a new Message`);
resEvents.write(
`data: From Url: ${Math.floor(Math.random() * 5000) + 1}\n\n`
);
} else {
res.writeHead(200, { "Content-Type": "text/html" });
res.end(`First go to http://localhost:8000/`);
}
return;
}
// Client side logs message data to console
res.writeHead(200, { "Content-Type": "text/html" });
res.end(`
<script>
var eventSource = new EventSource('/events');
eventSource.onmessage = function(event) {
console.log(event.data);
};
</script>
`);
});
server.listen(8000);
Update
I added sendMessageToBrowser
function. It's inside a setInterval
so you can see the server is sending max 50 messages to the browser one every second.
Upvotes: 1