Одним из УТП Svelte, конечно же, является его реактивность. Как с гордостью заявляет их домашняя страница

Больше никаких сложных библиотек управления состоянием — Svelte привносит реактивность в сам JavaScript

И в любой день разработка с помощью Svelte и его реактивной природы — это просто мечта. Вы можете указать Svelte отслеживать изменения состояния практически всего, используя директиву $:. И вполне вероятно, что ваши первые реактивные изменения дадут все ожидаемые результаты пользовательского интерфейса. Но по мере того, как вы начинаете больше полагаться на обновления пользовательского интерфейса, основанные на изменениях переменных или массивов/объектов, вполне вероятно, что ваш пользовательский интерфейс начнет пропускать биты и отбрасывать значения, о которых вы точно знаете.

Из-за постоянного потока обновленных данных фидов, которые обрабатывает Feed Army, я тоже столкнулся с этой проблемой. По мере того, как мои каналы будут обновляться, пользовательский интерфейс будет пытаться реактивно перебирать каждую из новых записей каналов для пользовательского дисплея. Тем не менее, записи в ленте были удалены при обновлении пользовательского интерфейса, и я не понимаю, почему?

Чтобы помочь, давайте рассмотрим этот простой/распространенный пример, который прекрасно иллюстрирует проблему. Предлагаю просмотреть REPL: svelte.dev/repl/567089d42c3b4146820e51ebb38b6f59, нажать кнопку + и просмотреть вывод вкладки консоли. Вы также можете поэкспериментировать, удалив вызов await tick();, чтобы увидеть вывод консоли 4x '1'.

Здесь исходный код для уточнения:

<script>
  import { tick } from "svelte";
  let element;
  let number = 1;
  async function onClick() {
    number++;
    console.log(element.textContent); // will be 1
    
    number = 2;
    console.log(element.textContent); // will be 1
    number = 3;
    console.log(element.textContent); // will be 1
    await tick(); // Remove this all to see 1 4x times
    // will be 3, the last change on the number variable
    console.log(element.textContent);
}
</script>
<div bind:this={element}>{number}</div>
<button on:click={onClick}> + </button>

Итак, что здесь происходит, почему консоль выводит 1, когда число связано с 2 и 3? И разумно, почему автор добавил await tick();? На это лучше всего ответит официальная документация: svelte.dev/tutorial/tick.

Когда вы обновляете состояние компонента в Svelte, DOM обновляется не сразу. Вместо этого он ожидает следующей микрозадачи, чтобы увидеть, есть ли какие-либо другие изменения, которые необходимо применить, в том числе в других компонентах.

И, конечно же, это имеет смысл, так как можно оптимизировать, чтобы остановить сжигание циклов процессора и разрешить пакетное обновление пользовательского интерфейса. Как только вы узнаете, почему пользовательский интерфейс не обновляется так, как вы думаете, вы можете предпринять шаги, чтобы справиться с этим поведением. В моем случае я использовал логический флаг, чтобы сообщить коду приложения, что обновления доступны. Затем обработка была завершена с использованием очереди на основе пользовательского магазина Svelte. Таким образом, код пользовательского интерфейса реагировал на обновления и мог обрабатывать каждую новую запись в ленте через очередь, чтобы гарантировать, что ни одна запись не будет пропущена.

Если вас больше интересуют реактивные магазины Sveltes (вы должны быть блестящими), я сделал еще один избранный пост о моем реактивном магазине очереди здесь.

Я надеюсь, что разъяснив, как вы связаны с "микрозадачами" Sveltes, вы сможете спроектировать свой код так, чтобы максимизировать его поведение.

Первоначально опубликовано на https://www.kylehq.com.