skip to Main Content

I want my Svelte SPA to interact with some data from a DB. For this, I used Sapper, so I can open the connection to DB in the server.js, and listen to it through its pub/sub mechanism. How can I then parse the message to my reactive store? here, channelArray is just a writable([]) imported from a ‘/.store.js’
With this code, I can parse to the App data to the store, but only when initialized?

// server.js


import sirv from 'sirv';
import polka from 'polka';
import compression from 'compression';
import * as sapper from '@sapper/server';
import { channelArray, chNum } from './components/store.js';

const { PORT, NODE_ENV } = process.env;
const dev = NODE_ENV === 'development';



polka() // You can also use Express
    .use(
        compression({ threshold: 0 }),
        sirv('static', { dev }),
        sapper.middleware()
    )
    .listen(PORT, err => {
        if (err) console.log('error', err);
    });



const Redis = require('ioredis');
const chpattern = "vac:*";
const sub = new Redis();


sub.psubscribe(chpattern);  
sub.on("pmessage", function (pattern, channel, message) { 
      console.log(`REDIS updated, number of channels`);
      chNum.subscribe(value => {console.log(value)});
      console.log(`Channel ${channel} Received msg: ${message}`);
  var ch = parseInt( channel.slice(4) );
  //if (ch >= 0 && ch < chNum ) { 
  if (ch >= 0 ) { 
      console.log('REDIS updated');
          channelArray[ch].value = message;
          channelArray[ch].lastupdate = Date.now();
  } 
});

And the relevant part of the index.html


<script>
       import Ctrlbox from '../components/Ctrlbox.svelte';
       import { channelArray, chNum } from '../components/store.js';
       import Blinkbox from '../components/blinkbox.svelte'

       let ch = 0;

       const addChannel = () => {
        $channelArray = [...$channelArray, {
        id: ch++,
            value: 0,
            lastupdate: new Date()
        }];
       };


       const box = [0,1,2];

       for (var i=0; i< box.length; i++) {
           addChannel();
       }
       chNum.set(ch);


</script>

2

Answers


  1. Seems to me that you directly manipulating the store. I don’t think that is the best approach. According to the docs a writable has a set and update method. You use set when you want to change the value of the variable and don’t care about the previous value. update is used if you care about the previous value, so for incrementing for example.

    It seems that update would fit your use case, as you seem to care about the previous state. So I would propose this:

     const addChannel = () => {
       channelArray.update(oldState => ([
         ...oldState,
         { id: ch++,
         value: 0,
         lastupdate: new Date() }
       ]));
     };
    
    Login or Signup to reply.
  2. While this on the backend

    import { channelArray, chNum } from './components/store.js';
    

    technically works, it does not do what you expect. The imported channelArray on the backend is not the same as on the frontend, they’re different instances of writable and there’s no connection or binding between them.

    You’ll need to add some sort of communication between front- and backend. AJAX requests or socket io, whatever suits best. Some REST API is probably the easiest solution.

    I went through this with an electron app, but there I can use the built in IPC so that the frontend and backend can exchange data.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search