Как стать автором
Обновить

Обеспечение реактивной чистоты в функциях на основе сигналов

Уровень сложностиСредний
Время на прочтение2 мин
Количество просмотров1.1K

Введение

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

Проблема

При написании функций, которые читают сигналы, легко — особенно в больших кодовых базах — непреднамеренно ввести побочные эффекты. Например, утилита для обновления сигнала может при определённых условиях зарегистрировать дополнительные реактивные «производители». Эти скрытые побочные эффекты могут привести к утечкам памяти, неожиданным повторным вычислениям или трудно отлавливаемым ошибкам при чтении или записи сигналов. Без проверки того, что функция остаётся «реактивно чистой», разработчикам приходится полагаться на код ревью, что ненадёжно, и отнимает много времени.

Общее решение

Чтобы решить эту задачу на уровне функций — независимо от конкретного фреймворка тестирования — мы можем ввести «проверку реактивной чистоты». Основная идея: выполнить функцию в контролируемом реактивном контексте, который отслеживает любые регистрации производителей (другими словами вызовы сигналов). После выполнения функции нужно проанализировать контекст: если были зарегистрированы производители, значит, функция нарушила реактивную чистоту. Набросок реализации на TypeScript может выглядеть так:

function isReactivePure(fn: () => void): boolean {
  // Создаём изолированный реактивный контекст
  const reactiveNode: ReactiveNode = Object.create(REACTIVE_NODE);
  const prevConsumer = setActiveConsumer(reactiveNode);
  
  reactiveNode.consumerAllowSignalWrites = true;

  try {
    fn(); // Вызываем переданную функцию
  } finally {
    setActiveConsumer(prevConsumer);
  }

  // Если в контексте записаны "производители", реактивная чистота функции нарушена
  return !reactiveNode.producerNode?.length;
}

Предложение по интеграции с Jest

Наличие такой проверки уже полезно, но интеграция её в API матчер-ов Jest сделает написание тестов ещё удобнее. Вместо того чтобы вызывать вспомогательную функцию и вручную проверять её логический результат, разработчики смогут писать понятные тесты:

it('не должен иметь побочных эффектов', () => {
  expect(() => {
    someMethodThatCallSignals();
  }).toBeReactivePure();
});

Здесь toBeReactivePure внутри создаёт реактивный контекст, выполняет переданную функцию и выдаёт подробное сообщение об ошибке, если были зарегистрированы производители. Благодаря такому расширению Jest команды смогут гарантировать реактивную чистоту по всему проекту с минимальным количеством шаблонного кода.

Нужна ваша поддержка

Эта функциональность повысит надёжность реактивного кода в Angular-проектах и за их пределами. Просим вас поддержать инициативу: перейдите к предложению в репозитории jest-preset-angular и поставьте 👍 реакцию. Ваша поддержка поможет приоритетизировать эту доработку и принести проверку реактивной чистоты в ваш любимый фреймворк тестирования!

— Удачной разработки без побочных эффектов!

Теги:
Хабы:
0
Комментарии0

Публикации

Работа

Ближайшие события