I have a svelte component named [symbol].svelte in which I want to initiate a connection to a streaming service to receive server-sent events. I've not found a way to do this successfully.
Since EventSource only runs in the browser, I initialized it in the onMount
function like so:
<script>
export let quote;
let sse = {};
onMount(async () => {
sse = new EventSource(`https://myurl.com?symbol=${quote.symbol}`);
sse.onmessage = (event) => {
let response = JSON.parse(event.data);
if(!response.length) return;
quote = response[0];
}
});
onDestroy(() => {
if(sse.readyState && sse.readyState === 1) {
sse.close();
}
})
</script>
<div>{quote.symbol}</div>
This works fine, except when I navigate to another route that uses the same component- since the component doesn't unmount and remount, onMount()
doesn't fire and thus doesn't instantiate a new SSE request. I don't know of any way to easily force the component to remount, which would be simplest (relevant github issue here)
Another try was using a reactive statement like so:
<script>
export let quote;
let sse = {};
$: {
if(process.browser === true) { //again, this stuff won't run on the server
if(sse.readyState && sse.readyState === 1) {
sse.close();
}
sse = new EventSource(`https://myurl.com?symbol=${quote.symbol}`);
}
}
sse.onmessage = (event) => {
let response = JSON.parse(event.data);
quote = response[0];
console.log(quote);
}
</script>
<div>{quote.symbol}</div>
When changing routes, the quote variable changed, thus triggering the reactive statement to kill the existing SSE and instantiate a new one. Exceptthe onmessage handler wouldn't fire, probably because the onmessage handler gets attached before the eventsource object is created.
Last take was to try with the onmessage handler in the reactive statement like so:
<script>
export let quote;
let sse = {};
$: {
if(process.browser === true) { //again, this stuff won't run on the server
if(sse.readyState && sse.readyState === 1) {
sse.close();
}
sse = new EventSource(`https://myurl.com?symbol=${quote.symbol}`);
sse.onmessage = (event) => {
let response = JSON.parse(event.data);
quote = response[0];
console.log(quote);
}
}
}
</script>
<div>{quote.symbol}</div>
The problem here is that since quote
gets reassigned as a product of the onmessage
handler, the reactive statement keeps firing circularly.
At this point I'm at a loss, any input would be appreciated!
from How to run server-sent events in svelte component in sapper
No comments:
Post a Comment