【发布时间】: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 => ({ x: point.time, y: point.value }))这样的东西。每次您的商店更新时,这也会触发重新渲染。或者更好的是,预测您商店中的转换,并相应地格式化数据:data = [...data, {x: time, y: value}],并在您的绘图中直接使用{$datastream}(这也会触发每次商店更新时的重新渲染)。
标签: javascript arrays websocket svelte svelte-store