Batch-обновления

FAST Element предоставляет мощный механизм работы с веб-компонентами, позволяющий эффективно управлять изменениями данных и обновлениями DOM. Одной из ключевых концепций, обеспечивающих высокую производительность, являются batch-обновления — группировка изменений для минимизации лишних перерасчетов и перерисовки.


Основы batch-обновлений

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

Batch-обновление объединяет несколько изменений в одну операцию, обеспечивая:

  • Сведение к минимуму лишних перерисовок.
  • Синхронизацию всех зависимых вычислений.
  • Эффективное управление сложными интерфейсами с множественными свойствами.

В FAST Element это реализовано через систему очередей обновлений.


Механизм очередей обновлений

FAST Element использует внутренний механизм microtask-очереди, чтобы выполнять обновления после завершения текущего стека вызовов. Принцип работы:

  1. Изменение свойства компонента вызывает вызов requestUpdate().
  2. FAST Element добавляет компонент в очередь обновлений.
  3. Все изменения свойств, произошедшие до следующей microtask, объединяются.
  4. После выполнения текущего стека, очередь обновлений обрабатывается единожды, вызывая метод update() и перерисовку DOM.

Пример кода, демонстрирующий batch-обновления:

import { FASTElement, html, css } from "@microsoft/fast-element";

const template = html<MyComponent>`
  <div>Счётчик: ${x => x.count}</div>
`;

class MyComponent extends FASTElement {
  count = 0;

  increment() {
    this.count += 1;
    this.count += 1;
    this.count += 1;
  }
}

FASTElement.define({
  name: "my-component",
  template,
  styles: css`div { color: blue; }`,
  type: MyComponent
});

В методе increment() три изменения свойства count будут объединены в одну отрисовку, благодаря batch-обновлению. В DOM появится значение 3 после одного обновления, а не три отдельных перерисовки.


Использование requestUpdate() для ручного контроля

В некоторых случаях требуется явный контроль за обновлениями, например, при работе с асинхронными данными или сложными вычислениями. FAST Element предоставляет метод requestUpdate(), который позволяет:

  • Запланировать обновление компонента.
  • Передать ключ свойства для отслеживания конкретного изменения.
  • Возвратить Promise, который разрешается после завершения обновления.

Пример:

async fetchData() {
  const response = await fetch("/data.json");
  this.data = await response.json();

  await this.requestUpdate("data"); // Обновление DOM после загрузки данных
  console.log("Компонент обновлён с новыми данными");
}

Использование requestUpdate() обеспечивает точную синхронизацию состояния компонента с его визуальным представлением.


Оптимизация batch-обновлений

Для больших интерфейсов с множеством компонентов рекомендуется:

  1. Сокращать количество реактивных свойств, отслеживать только изменяющиеся данные.
  2. Группировать изменения в одном вызове метода, чтобы избежать множества микротасков.
  3. Использовать computed-свойства, которые автоматически пересчитываются при изменении зависимостей, не вызывая лишние обновления.

Пример computed-свойства:

import { FASTElement, observable, computed } from "@microsoft/fast-element";

class CartComponent extends FASTElement {
  @observable items = [];

  @computed get total() {
    return this.items.reduce((sum, item) => sum + item.price, 0);
  }
}

Здесь любое изменение массива items инициирует пересчёт total, который будет включён в batch-обновление, предотвращая множественные обновления DOM.


Batch-обновления и событийная модель

FAST Element обеспечивает корректное взаимодействие batch-обновлений с событиями:

  • События срабатывают после обновления DOM, что позволяет работать с актуальными элементами.
  • При изменении нескольких свойств одновременно событие updated вызывается один раз для всех изменений.

Пример:

class MyCounter extends FASTElement {
  count = 0;

  increment() {
    this.count += 1;
    this.count += 2;
    this.addEventListener('updated', () => console.log('Обновление завершено'));
  }
}

В консоли будет выведено одно сообщение после объединённого обновления, а не несколько.


Batch-обновления и производительность

Batch-обновления критичны для высокой производительности интерфейсов с большим числом реактивных компонентов:

  • Снижение нагрузки на рендеринг: DOM обновляется один раз для множества изменений.
  • Снижение числа вычислений: вычисляемые свойства пересчитываются единожды.
  • Устойчивость к асинхронным изменениям: изменения, поступающие из промисов или событий, автоматически объединяются в единую очередь.

В сочетании с requestUpdate() и computed-свойствами batch-обновления позволяют создавать масштабируемые и отзывчивые веб-компоненты без лишней нагрузки на браузер.


Batch-обновления в FAST Element являются ядром реактивной системы и обеспечивают эффективное управление состоянием и DOM, позволяя создавать высокопроизводительные, масштабируемые веб-приложения.