Closed unknownsoldier08 closed 7 months ago
Hi @unknownsoldier08 ,
Try this
// src/routes/events/+server.js
import { events } from 'sveltekit-sse';
/**
* @param {number} milliseconds
* @returns
*/
function delay(milliseconds) {
return new Promise(function run(resolve) {
setTimeout(resolve, milliseconds);
});
}
export function POST({ request }) {
return events({
request,
async start({ emit }) {
// eslint-disable-next-line no-constant-condition
while (true) {
const date = new Date();
emit(
'time',
`Hello, the time is ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}.`
);
await delay(1000);
}
}
});
}
<!-- src/routes/+page.svelte -->
<script>
import { source } from 'sveltekit-sse';
/**
* @type {?import('svelte/store').Readable<string>}
*/
let time;
function start() {
time = source('/events').select('time');
}
</script>
{#if !time}
<button on:click={start}>
<span>What time is it?</span>
</button>
{:else}
{$time}
{/if}
When you call source()
, the underlying connection is being cached based on the path you're passing in, in that example '/events'
.
Subsequent calls to source()
will simply return the existing connection.
If you want to add a disconnect button then you simply do this
<!-- src/routes/+page.svelte -->
<script>
import { source } from 'sveltekit-sse';
/**
* @type {?import('svelte/store').Readable<string>}
*/
let time;
function start() {
time = source('/events').select('time');
}
function stop() {
source('/events').close();
time = null;
}
</script>
{#if !time}
<button on:click={start}>
<span>What time is it?</span>
</button>
{:else}
{$time}<br />
<button on:click={stop}>
<span>Okay, thanks.</span>
</button>
{/if}
Note the stop()
function.
The final result will look like this
You can find the example repo here https://github.com/tncrazvan/sveltekit-sse-issue-30-example
@unknownsoldier08 let me know if this is what you're looking for.
I've tried your snippet and it seems to function as expected, but how should I satisfy typescript with it?
I have the following
<script lang="ts">
import { source } from 'sveltekit-sse';
import type { Readable } from 'svelte/store';
import { Button } from '$lib/components/ui/button';
let store: Readable<{ message: string } | null>
function start() {
if (store) return;
store = source('/api/test').select('message').json<{ message: string }>();
}
function stop() {
source('/api/test').close();
store = null; // tserror: Svelte: Type null is not assignable to type Readable<{ message: string; } | null>`
}
</script>
{#if store}
<Button variant="outline" on:click={stop}>Stop</Button>
{:else}
<Button variant="outline" on:click={start}>Start</Button>
{/if}
{$store?.message ?? 'No message'}
I change store to allow undefined, but not sure if that is right
<script lang="ts">
import { source } from 'sveltekit-sse';
import type { Readable } from 'svelte/store';
import { Button } from '$lib/components/ui/button';
let store: Readable<{ message: string } | null> | undefined;
function start() {
if (store) return;
store = source('/api/test').select('message').json<{ message: string }>();
}
function stop() {
source('/api/test').close();
store = undefined; // typescript doesn't complain now
}
</script>
{#if store}
<Button variant="outline" on:click={stop}>Stop</Button>
{:else}
<Button variant="outline" on:click={start}>Start</Button>
{/if}
{$store?.message ?? 'No message'}
@unknownsoldier08 this is what you're looking for
<script lang="ts">
import { source } from 'sveltekit-sse';
import type { Readable } from 'svelte/store';
let store: Readable<{ message: string } | null> | undefined;
function start() {
if (store) return;
store = source('/api/test').select('message').json<{ message: string }>();
}
function stop() {
source('/api/test').close();
store = undefined;
}
</script>
{#if null === store}
<button on:click={stop}>Stop</button>
{'No message'}
{:else}
<button on:click={start}>Start</button>
{$store?.message ?? 'No message'}
{/if}
You can see the return type of .json()
in your editor
the .json()
method itself can return null
.
Awesome, will go with this. Thanks for your help!
It seems like by default, once a component is loaded - it will automatically connect to the sse source
How can I make it, so that it will only connect on demand (ie. on button click)
Is there any example?
Thank you