【问题标题】:How to run server-sent events in svelte component in sapper如何在 sapper 的 svelte 组件中运行服务器发送的事件
【发布时间】: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


【解决方案1】:

听起来您想使用{#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 = {}赋值或检查@ 987654329@.

【讨论】:

  • 啊,这样就行了。我将 SSE 代码放在一个关键块中的组件中,瞧。谢谢!
猜你喜欢
  • 2020-06-06
  • 2020-11-08
  • 2020-06-20
  • 2021-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-24
相关资源
最近更新 更多