Sunday, 14 August 2022

JS: Server-sent events

G'day:

Yes, it's very odd for me to have something to say about JS stuff. I don't imagine there's anything new here for people that actually do JS development, but I don't, so this feature is new to me. Maybe it'll be new to some of my readers too.

I was looking at a question on Stack Overflow tagged with "ColdFusion": Server Side Events and Polling Database for new records with Lucee/Coldfusion. There was no answer, and I didn't know what the questioner was on about, so I decided to have a look.

Firstly, I RTFMed the JS words I didn't recognise:

The from ferreting around in the docs further, I found a PHP example of the server-side part: MDN › References › Web APIs › Server-sent events › Using server-sent events

From that lot it was easy to knock-together a CFML example.

<!-- test.html -->

<div id="result"></div>

<script>
var source = new EventSource('testInLoop.cfm');

source.addEventListener('message', function(e){
    document.body.innerHTML += `${e.data}<br>`
});
</script>
// testInLoop.cfm

header name="Content-Type" value="text/event-stream";

requestStartedAt = now()
for (i=1; i <= 10; i++) {
    data = {
        "uuid" = createUuid(),
        "now" = now().timeFormat("HH:mm:ss"),
        "requestStartedAt" = requestStartedAt.timeFormat("HH:mm:ss")
    }
    writeOutput("event: message" & chr(10))
    writeOutput('data: #serializeJson(data)#' & chr(10) & chr(10))
    flush;
    sleep(1000)
}
writeOutput("event: message" & chr(10))
writeOutput('data: #serializeJson({"complete": true})#' & chr(10) & chr(10))
flush;

Miraculaously, this works:

{"uuid":"4E1A4D17-6E4A-410B-B9C26B420A0DD5B4","now":"11:15:40","requestStartedAt":"11:15:40"}
{"uuid":"65C3F605-8823-4BF5-B32550FEABD0CECC","now":"11:15:41","requestStartedAt":"11:15:40"}
{"uuid":"D22E86D0-872F-4E5F-A89B29F44314BE05","now":"11:15:42","requestStartedAt":"11:15:40"}
{"uuid":"C4B6C1A6-0EF6-4CFD-AC9D4791F14A74AA","now":"11:15:43","requestStartedAt":"11:15:40"}
{"uuid":"FE0DB9CA-3535-416C-B63066EC4913E87D","now":"11:15:44","requestStartedAt":"11:15:40"}
{"uuid":"3E4E2DED-5B57-40AB-B8F5886DC7983053","now":"11:15:45","requestStartedAt":"11:15:40"}
{"uuid":"19611965-34D0-4ED4-9B9260B7EE3D8941","now":"11:15:46","requestStartedAt":"11:15:40"}
{"uuid":"81C7066F-55AD-47F1-BBBEC6EDAAA7A7C4","now":"11:15:47","requestStartedAt":"11:15:40"}
{"uuid":"2477899D-50EB-4CB0-AAF8E681DF168087","now":"11:15:48","requestStartedAt":"11:15:40"}
{"uuid":"7ABF54BD-1618-458D-A6BBF5D07812564D","now":"11:15:49","requestStartedAt":"11:15:40"}
{"complete":true}
{"uuid":"44AA5416-8EA9-451B-95C60E2BC1F4CEF8","now":"11:15:53","requestStartedAt":"11:15:53"}
{"uuid":"8829A145-93D5-4175-9305414B32CBE83E","now":"11:15:54","requestStartedAt":"11:15:53"}
{"uuid":"15F96712-263C-4798-ABCDBDC0C0AA68F7","now":"11:15:55","requestStartedAt":"11:15:53"}
{"uuid":"AF3A1831-8817-400E-B1292B4FCBD8BDDC","now":"11:15:56","requestStartedAt":"11:15:53"}
{"uuid":"C3D9D100-C8A9-4A92-87F6E62138DB5C6F","now":"11:15:57","requestStartedAt":"11:15:53"}
{"uuid":"1E60C5D6-E16A-429C-804D32B278272872","now":"11:15:58","requestStartedAt":"11:15:53"}
{"uuid":"DDB2DA3C-D064-4F6E-80227E337B41D657","now":"11:15:59","requestStartedAt":"11:15:53"}
{"uuid":"E7034B05-7912-4971-9ECD76E07403AD49","now":"11:16:00","requestStartedAt":"11:15:53"}
{"uuid":"D0D17279-6531-42B9-AB21FFB76DA5D939","now":"11:16:01","requestStartedAt":"11:15:53"}
{"uuid":"D804394F-DCB7-4FE3-BB6AAD86A4865D7D","now":"11:16:02","requestStartedAt":"11:15:53"}
{"complete":true}
{"uuid":"C25CF442-18FB-4BDD-8B55811E6DDCCD13","now":"11:16:06","requestStartedAt":"11:16:06"}

One thing to note is that once the server-side request completes, the browser (Chrome for me) re-polls the server after seemingly 4sec. I could not find anything in the docs about this (or how to set the interval). I've just tested in Edge and Firefox too, and their behaviour is the same as Chrome, except Firefox's interval seemed to be 6sec not 4sec.

That's all I have to say on this. Pleased to know about it, and pleased to be able to answer that Stack Overflow question now.

Righto.

--
Adam