【发布时间】:2021-03-03 09:10:50
【问题描述】:
我有一个名为 [symbol].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>
当更改路由时,quote 变量发生了变化,从而触发了响应式语句来杀死现有的 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 处理程序的产物,反应性语句不断循环触发。
此时我不知所措,任何意见将不胜感激!
【问题讨论】:
-
为什么不使用'afterUpdate',比较链接上的当前符号和变量上本地保存的符号,并确定是否实例化新的连接?
-
不确定它是如何工作的 - afterUpdate 会给我新值,但我如何将它与以前的值进行比较?
标签: javascript server-sent-events svelte svelte-3 sapper