Skip to content
Advertisement

How should I efficiently add to an array from a Svelte store subscription?

I’d like to have objects added to an array in a component each time a subscribed store gets updated. In this case, the store is receiving data from a WebSocket, and I ultimately want to plot the last N datapoints that I’ve received (N=1000 for example).

The store is defined in 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)
  }
})

I then have a Chart.svelte component which should a) plot the last N points (implementation not shown), b) update each time my store subscription callback occurs. The catch here is that I may need to do some minor conversion/preprocessing on the incoming WebSocket data. In my Chart.svelte we have (omitted the plotting stuff for brevity):

<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>

My question is; is this the best way to do this? I think it’s not – It works, but I’ve got a duplicate of the array of data in the datastream store, and each time I get a new value, I completely rebuild the plot_data array.

I had attempted to do this with only the most recent data point subscribed in the store, but I couldn’t figure out how to capture the store update and thereby force a new entry into the plot_data array (and thus, refresh the plot).

Advertisement

Answer

Is this what you are looking for:

See this repl: receive updates in batches

But use this store for your use:

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

const datastream = readable(null, set => {
  socket.onmessage = function (event) {
   set ({ time, value } = JSON.parse(event.data));
  };
});
5 People found this is helpful
Advertisement