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

Этот пост является частью следующей серии постов в блоге:

  1. async-states: библиотека управления состоянием
  2. асинхронные состояния: использование реакции
  3. асинхронные состояния: исходный объект
  4. асинхронные состояния: производитель
  5. асинхронные состояния: расширенные концепции
  6. асинхронные состояния: vs. response-query vs redux vs recoil
  7. реагировать-асинхронные-состояния: SSR

План

  • Что это ?
  • Мотивы для создания этой библиотеки
  • Проблеск силы библиотеки
  • Библиотечные примитивы и концепции
  • Документация и примеры использования

Что это ?

async-states — это набор инструментов для управления состоянием, который работает везде, где у вас есть среда выполнения JavaScript (это может быть браузер, сервер, рабочие процессы…).

Эта библиотека была разработана, чтобы уменьшить шаблон, необходимый для доступа и управления состоянием в данном приложении: вы можете получить полный контроль над состоянием из любого места в вашем приложении.

Ключевыми особенностями библиотеки являются:

  • Работает буквально везде
  • Минимальный размер пакета и отпечаток памяти
  • Синхронные и асинхронные потоки: Promises, async/await, генераторы или вообще ничего
  • Очень богатый API, который будет поддерживать все ваши варианты использования (даже подписки, веб-сокеты, тайм-ауты, интервалы…)
  • Дополнительные функции, такие как кеширование, повторная попытка, устранение ложных срабатываний и дросселирование…

Общее представление о возможностях можно получить в документации библиотеки.

Мотивы для создания этой библиотеки

Есть несколько государственных менеджеров, некоторые говорят, что государственный менеджер рождается каждый раз, когда вы зеваете, но не все государственные менеджеры созданы равными (Да здравствует async-states).

Я занимаюсь загадкой Javascript и управления состоянием уже почти десять лет, а с React — 7 лет, так что я в основном видел (за исключением Redux), как рождались все остальные и как они развивались с течением времени. Тем не менее, я всегда чувствую, что чего-то не хватает в головоломке.

Я начал писать код еще в 2010 году и использовал множество языков и платформ, каждая из которых имеет свои спецификации, API и ограничения. В последние годы я написал МНОГО корпоративных приложений для разных предприятий и корпораций, в основном используя Java и JavaScript. Это позволило мне не только иметь четкое представление об API для проектирования и создания, но и о том, как использовать его для решения всех проблем, с которыми я когда-то сталкивался, управляя состоянием с помощью пользовательского интерфейса.

Итак, в основном я хочу:

  • Меньше кода и больше возможностей
  • Согласованное и эффективное управление состоянием, синхронизация или асинхронность
  • Отменить любой асинхронный поток автоматически и/или императивно
  • Генераторы поддерживают «истинные» отмены
  • Поддержка кэширования по запросу и повторных попыток, а также взаимное использование кэша
  • Такие эффекты, как подавление дребезга и дроссель
  • Подписывайтесь и управляйте любым состоянием из любого места
  • Пропустить и настроить ожидающее поведение перехода
  • И что более важно, все предыдущие аспекты должны работать вместе!

Следите за новостями, чтобы узнать, чем async-states уникален.

Проблеск силы библиотеки

Задержи дыхание; это debounced-cancellable-cached — с заголовком управления кешем max-age — поиск по мере ввода, который пропускает состояние ожидания, если поиск отвечает менее чем через 300 мс, и который остается в состоянии ожидания не менее 300 мс до избежать мерцания пользовательского интерфейса:

Попробуйте сами в этой песочнице кодов!

Давайте сначала поговорим о свойствах, использованных в предыдущем примере:

  • key: Уникальный идентификатор штата, к нему можно подключиться откуда угодно.
  • producer: Это функция, которая возвращает значение нашего состояния (или выдает его), может быть любой формы и выполнять невероятные задачи.
  • skipPendingDelayMs : Если запрос выполняется достаточно быстро, статус pending будет полностью пропущен.
  • keepPendingForMs : Если ваш пользовательский интерфейс переходит в состояние ожидания, сохраните это состояние как минимум на это время, чтобы пользовательский интерфейс не мигал, показывая какой-либо индикатор и немедленно размонтируя его, если запрос отвечает сразу после этого.
  • runEffect и runEffectDurationMs : эффект, применяемый к runs , на данный момент может быть debounce или throttle.
  • cacheConfig : Применяемая конфигурация кэша. Если не предусмотрена функция getDeadline для настройки времени кэширования для каждого состояния, и если данные представляют собой объект, подобный объекту Response, предпринимается попытка заголовка управления кэшем, и maxAge будет взято автоматически.

Если вы занимаетесь фронтенд-разработкой, вы должны знать, насколько деликатной будет реализация всех этих функций для совместной работы и последовательной работы. Но для библиотеки это даже не зависит от реакции или цикла рендеринга.

Это самое основное использование библиотеки, и ее возможности не имеют ничего общего с этим небольшим примером, взгляните на всю сигнатуру useAsyncState, если вам любопытно!

Вы также можете использовать основную библиотеку с реакцией напрямую: вот предыдущий пример с использованием useSyncExternalStore вместо useAsyncState:

Библиотечные примитивы и концепции

Концепции

Чтобы использовать библиотеку, вы должны ознакомиться с этими понятиями:

  • State : Состояние, используемое и предоставляемое библиотекой, содержит 4 свойства: status, timestamp, data и props. Подробнее о них можно узнать в документации.
  • The producer: Функция, отвечающая за получение значения состояния, называется producer: она выдает значение состояния. Это может быть синхронная функция, функция, возвращающая обещание, синтаксис async/await, генераторы или даже нулевое значение для управления состоянием на лету. Подробнее читайте в документах.
  • source: Исходный объект берется из библиотеки из нескольких мест, и это оболочка вокруг экземпляра внутреннего состояния библиотеки, позволяющая полностью контролировать: состояние чтения, запуск производителя, манипулирование конфигурацией, присоединение событий, замену кеша или даже императивное изменение государственная ценность. Наиболее распространенный способ их создания — через функцию createSource. Его можно вызывать везде, и если запрошенное состояние (по ключу) уже существует, то оно будет использовано.

Исходный объект

На момент написания этого поста объект библиотеки source имел следующую форму:

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

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

Продюсер

Для краткости поста я рекомендую проверить документы для производителя, здесь мы пока обсудим только его сигнатуру и мощность.

Вот определение типа producer:

Где ProducerProps определяются как:

Читайте о них здесь.

Производитель может:

  • Зарегистрируйте обратные вызовы отмены, чтобы очистить его работу (прервать выборку, завершить рабочий процесс, очистить тайм-аут/интервал, отключить веб-сокет…)
  • Получить некоторый контекст для текущего запуска из args или payload
  • Доступ к последнему успешному состоянию. Это может быть полезно для любого типа производителей, использующих предыдущее успешное состояние, таких как редюсеры и бесконечные списки.
  • Проверьте, не было ли оно прервано, чтобы решить, продолжать ли работу в контексте, который не прерывается автоматически, например в промисах или асинхронном/ожидающем синтаксисе. В библиотеке есть генератор-раннер «одного» уровня, который автоматически прекращает работу после прерывания.
  • Run и получить функцию прерывания любого другого состояния, к которому у него есть доступ, с возможностью выполнения каскадных отмен.
  • Запустить и получить обещание через runp
  • Выполнять с использованием обратных вызовов при изменении статуса через runc
  • Выбрать текущее состояние любого другого состояния по его объекту key или source
  • emit состояние обновляется после разрешения; это оптимизация для производителей подписки, таких как websockets или интервалы, например: если нет явного вызова нового run или abort, вы можете изменить состояние от производителя с помощью функции emit без потери этой связи.
  • abort собственный пробег; если производитель не перешел в состояние pending при вызове этой функции, он будет полностью спасен.

Если вы дошли до этого момента, поздравляем! Вы должны знать о многих функциях библиотеки.

Документация и примеры использования

Библиотеку можно использовать во многих случаях ежедневного использования;

Получение данных

Наиболее распространенный вариант использования — выборка данных; вы обнаружите, что пишете много такого кода:

Обмен состоянием и манипулирование

Библиотека также может управлять синхронными состояниями, если производитель опущен или если он не возвращает промис.

Если производитель не указан, функция run делегирует работу функции setState: она обновит состояние на заданное значение, если ей была задана функция, она получит текущее состояние. Рассмотрим следующий пример

useAsyncState может получить в качестве параметра только ключ state (строка), а все остальное сделает за вас! Протестируйте предыдущий пример здесь.

Заключение

Готов поспорить, что к настоящему моменту вы прекрасно понимаете, как библиотека может решить все ваши повседневные проблемы и значительно повысить производительность и уверенность в себе.

В следующем разделе мы увидим, насколько хорошо библиотека работает с React и сколько возможностей она дает на практике.