【问题标题】:How should I efficiently add to an array from a Svelte store subscription?我应该如何有效地从 Svelte 商店订阅添加到数组?
【发布时间】:2021-03-04 06:11:35
【问题描述】:

我希望每次更新订阅的存储时都将对象添加到组件中的数组中。在这种情况下,商店正在从 WebSocket 接收数据,我最终想要绘制我收到的最后一个 N 数据点(例如 N=1000)。

商店定义在socket.js:

import { readable } from 'svelte/store';

export const datastream = readable([], set => {
  let socket = new WebSocket("ws://localhost:8765")
  let data = [];

  socket.onmessage = function (event) {
    let { time, value } = JSON.parse(event.data);

    // update the data array
    // TODO: set a max buffer size
    data = [...data, {"time": time, "value": value}];

    // set the new data as store value
    set(data)
  }
})

然后我有一个 Chart.svelte 组件,它应该 a) 绘制最后一个 N 点(未显示实现),b) 每次我的商店订阅回调发生时更新。这里的问题是我可能需要对传入的 WebSocket 数据进行一些小的转换/预处理。在我的Chart.svelte 中,我们有(为简洁起见,省略了绘图内容):

<script>
  ...
  import { datastream } from './socket.js';

  export let plot_data;

  const unsubscribe = datastream.subscribe(data => {
    plot_data = []
    for (let datum of data) {
      plot_data = [...plot_data, {x: datum.time, y: datum.value}]
    }
  });

  $: {...
      some stuff that sets up plotting
  ...}
</script>

<div class='my-chart'>
    ...(plot_data)
</div>

我的问题是;这是最好的方法吗?我认为不是 - 它可以工作,但是我在 datastream 存储区中有一个数据数组的副本,每次我得到一个新值时,我都会完全重建 plot_data 数组。

我曾尝试仅使用商店中订阅的最新数据点来执行此操作,但我不知道如何捕获商店更新,从而强制在 plot_data 数组中添加一个新条目(因此,刷新情节)。

【问题讨论】:

  • 我认为在存储中保存最新的 N 个数据点是正确的想法 - 这允许您卸载和重新安装图表组件,并且不会在此过程中丢失任何数据,这是您不会的如果商店只保存最新的单个数据点,就可以做到。但是,我不明白为什么你要在组件中重建整个数据数组,你能解释一下吗?
  • 在这种情况下,我的商店对象看起来像{"time": "20:03:24", "value": 2.103},但要将其放入绘图中,我想构造一个反映绘图对象所需输入的对象(即{x: value, y: value}) .一般来说,我可能必须以某种方式操作对象值(即格式化时间戳字符串)。换句话说,我不能按原样将商店直接输入图表。如果没有 for 循环,我无法弄清楚如何做到这一点。
  • 我现在明白你的意思了,我愚蠢地使用了 for 循环,而我应该使用“推送”到顶级定义的数组 plot_data。然后我可以根据需要操作传入的数据点并将其添加到数组中……但是,要触发更新,我必须执行plot_data = plot_data……我想这比 for 循环更有效。跨度>
  • 我认为即使是带有map 的简单反应规则也可以解决问题。像$: plot_data = $datastream.map(point =&gt; ({ x: point.time, y: point.value })) 这样的东西。每次您的商店更新时,这也会触发重新渲染。或者更好的是,预测您商店中的转换,并相应地格式化数据:data = [...data, {x: time, y: value}],并在您的绘图中直接使用{$datastream}(这也会触发每次商店更新时的重新渲染)。

标签: javascript arrays websocket svelte svelte-store


【解决方案1】:

这是你要找的东西吗:

查看此回复:receive updates in batches

但请使用这家商店供您使用:

let socket = new WebSocket("ws://localhost:8765")

const datastream = readable(null, set => {
  socket.onmessage = function (event) {
   set ({ time, value } = JSON.parse(event.data));
  };
});

【讨论】:

  • 基本上就是这样,正如@ThomasHennes 的评论中提到的那样,推动是我首先应该做的。我将不得不尝试使用派生存储 - 我不确定这里是否有必要,或者在数据/内存方面是否会更有效。接受这个,因为它解决了原来的问题。
猜你喜欢
  • 2020-07-29
  • 1970-01-01
  • 1970-01-01
  • 2022-07-21
  • 2018-04-02
  • 1970-01-01
  • 2021-08-09
  • 2019-06-12
  • 2021-12-23
相关资源
最近更新 更多