如何在 sapper 的 svelte 组件中 运行 服务器发送事件
How to run server-sent events in svelte component in sapper
我有一个名为 [symbol].svelte 的 svelte 组件,我想在其中启动与流媒体服务的连接以接收服务器发送的事件。我还没有找到成功执行此操作的方法。
由于 EventSource 仅在浏览器中运行,因此我在 onMount
函数中对其进行了初始化,如下所示:
<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>
这工作正常,除非我导航到另一个使用相同组件的路由 - 因为该组件不会卸载和重新安装,所以 onMount()
不会触发,因此不会实例化新的 SSE要求。我不知道有什么方法可以轻松地强制组件重新安装,这将是最简单的(相关 github 问题 here)
另一种尝试是使用像这样的反应式语句:
<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>
更改路由时,引用变量发生更改,从而触发反应式语句杀死现有的 SSE 并实例化一个新的。除了 onmessage 处理程序不会触发,可能是因为在创建事件源对象之前附加了 onmessage 处理程序。
最后一次尝试在反应语句中使用 onmessage 处理程序,如下所示:
<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>
这里的问题是,由于 quote
被重新分配为 onmessage
处理程序的产物,因此反应语句会循环触发。
此时我不知所措,任何输入将不胜感激!
听起来你想使用 {#key ...}
,这会导致其内容在值更改时被拆除并重新创建,包括组件:
{#key quote}
<!-- destroyed and recreated whenever `quote` changes -->
<Quote {quote}/>
{/key}
文档在这里:https://svelte.dev/docs#key
顺便说一句,如果 onDestroy
仅用于清理发生在 onMount
中的工作,则没有必要使用它:
onMount(() => {
const 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];
}
};
return () => {
if(sse.readyState === 1) {
sse.close();
}
});
});
这样更好,因为你没有顶级sse
变量,而且因为返回的清理函数只需要在浏览器中,你不需要占位符ssr = {}
赋值或检查 sse.readyState
.
我有一个名为 [symbol].svelte 的 svelte 组件,我想在其中启动与流媒体服务的连接以接收服务器发送的事件。我还没有找到成功执行此操作的方法。
由于 EventSource 仅在浏览器中运行,因此我在 onMount
函数中对其进行了初始化,如下所示:
<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>
这工作正常,除非我导航到另一个使用相同组件的路由 - 因为该组件不会卸载和重新安装,所以 onMount()
不会触发,因此不会实例化新的 SSE要求。我不知道有什么方法可以轻松地强制组件重新安装,这将是最简单的(相关 github 问题 here)
另一种尝试是使用像这样的反应式语句:
<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>
更改路由时,引用变量发生更改,从而触发反应式语句杀死现有的 SSE 并实例化一个新的。除了 onmessage 处理程序不会触发,可能是因为在创建事件源对象之前附加了 onmessage 处理程序。
最后一次尝试在反应语句中使用 onmessage 处理程序,如下所示:
<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>
这里的问题是,由于 quote
被重新分配为 onmessage
处理程序的产物,因此反应语句会循环触发。
此时我不知所措,任何输入将不胜感激!
听起来你想使用 {#key ...}
,这会导致其内容在值更改时被拆除并重新创建,包括组件:
{#key quote}
<!-- destroyed and recreated whenever `quote` changes -->
<Quote {quote}/>
{/key}
文档在这里:https://svelte.dev/docs#key
顺便说一句,如果 onDestroy
仅用于清理发生在 onMount
中的工作,则没有必要使用它:
onMount(() => {
const 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];
}
};
return () => {
if(sse.readyState === 1) {
sse.close();
}
});
});
这样更好,因为你没有顶级sse
变量,而且因为返回的清理函数只需要在浏览器中,你不需要占位符ssr = {}
赋值或检查 sse.readyState
.