Как я могу обновить только один элемент в массиве магазинов Svelte, не касаясь других? - PullRequest
0 голосов
/ 29 мая 2020

Думаю, этот вопрос больше касается JS sysntax, но у меня есть такой массив хранилища:

export const store = readable( {id: 0, value: 0} , set => {
    let socket = new WebSocket("ws://localhost:65432");
    socket.onmessage = function (event) {
        var data = JSON.parse(event.data);
        set({id: 0, value: data});
    }
})

Магазин определяет свой метод set для обновления значения из соединения через веб-сокеты. Как я могу сделать то же самое, но с массивом магазинов? Что-то вроде:

arr = [];
for(i=0; i<numberOfItems; i++) {
    arr = [...arr,{id: i, value: 0}];
}

export const store = readable( [{arr}] , set => {
    let socket = new WebSocket("ws://localhost:65432");
    socket.onmessage = function (event) {
        var data = JSON.parse(event.data);
        var channel = data.channel;
        set({id: data.channel, value: data.value});
    }
})

Вот где мне не удается «установить» массив и без необходимости объявлять весь массив при каждом обновлении.

Ответы [ 3 ]

0 голосов
/ 29 мая 2020

Вы можете получить доступ к фактическому значению читаемого хранилища также внутри обратного вызова. Затем вы можете обновить существующий массив без замены всего:

<script>
    import {readable} from 'svelte/store'

    let intervalHandle
    const arr = new readable(['Start'], (set) => {
        intervalHandle = setInterval(() => {
            set([...$arr, 'Another value'])     
        }, 1000)
    })

</script>

<h1>Readable demo</h1>
<button on:click={() => clearInterval(intervalHandle)}>Stop it</button>
{#each $arr as item}
<div>{item}</div>
{/each}
0 голосов
/ 29 мая 2020

Я думаю, что в вашем случае то, что вы хотите сохранить в магазине, - это не массив, а объект, это упростило бы этот шаг. Что-то вроде:

export const store = readable({} , set => {
    let channels = {};
    let socket = new WebSocket("ws://localhost:65432");
    socket.onmessage = function ({data}) {
        let { channel, value } = JSON.parse(data);

        // update `channels`
        channels = {...channels, [channel]: value };

        // set the new `channels` as store value
        set(channels)
    }
})

Обратите внимание, что таким образом у вас будет напрямую канал в качестве ключа объекта: поэтому, если канал уже существует, он будет обновлен, а не добавлен. И если он не существует, он будет добавлен.

Таким образом, у вашего подписчика может быть что-то вроде:

store.subscribe(channels => {
  for (let [channel, value] of Object.entries(channels)) {
    console.log(`channel ${channel} received ${value}`);
  }
});

В качестве последнего примечания, учтите, что этот код создает новый объект каждое обновление, чтобы избежать побочных эффектов, это обычная практика. Однако, если у вас много данных в объекте и вы знаете о возможных последствиях, вы можете просто добавить / обновить единственный ключ, не дублируя каждый раз объект, по причинам производительности / памяти.

Надеюсь, это поможет!

0 голосов
/ 29 мая 2020

Я думаю, что читабельное хранилище не решит вашу проблему, потому что здесь нет метода обновления. Почему бы вам вместо этого не попробовать хранилище с возможностью записи ? Он дает вам функцию обновления с текущим значением в качестве аргумента, поэтому вы можете сделать что-то вроде этого:

    let socket = new WebSocket("ws://localhost:65432");
    socket.onmessage = function(event) {
      var data = JSON.parse(event.data);
      var channel = data.channel;
      store.update(n => [...n, { id: data.channel, value: data.value }]);
    };

Вот REPL с примером того, как это работает. Он использует интервалы для имитации работы веб-перехватчиков. Если вы откроете консоль, вы увидите обновленное значение магазина.

...