Skip to Content
👋 Добро пожаловать в документацию lite-fsm!

Отмена эффектов

Отмена эффектов — важный механизм контроля асинхронных операций в конечных автоматах. lite-fsm предоставляет встроенные возможности для эффективного управления отменой эффектов при смене состояний.

Проблема асинхронных эффектов

В приложениях, использующих асинхронные операции (HTTP-запросы, таймеры, загрузка данных), могут возникать случаи, когда:

  • Пользователь переходит на другую страницу до завершения запроса
  • Новый запрос инициируется до завершения предыдущего
  • Состояние автомата меняется, делая результат асинхронной операции неактуальным

В таких случаях необходим механизм отмены эффектов.

Автоматическая отмена при смене состояния

По умолчанию, при смене состояния автомата эффекты не отменяются автоматически. Отмена эффектов происходит только при использовании опции type: "latest" в создании эффекта.

Важно понимать, что при отмене эффекта сам код уже запущенного эффекта продолжает выполняться, но игнорируются transition-вызовы внутри этого эффекта. То есть мы просто игнорируем результаты работы эффектов, но не прерываем их выполнение:

export const player = createMachine({ config: { IDLE: { CHANGE_TRACK: "LOAD_TRACK_DATA", }, LOAD_TRACK_DATA: { LOAD_TRACK_DATA_STARTED: "LOAD_TRACK_DATA_PENDING", }, LOAD_TRACK_DATA_PENDING: { LOAD_TRACK_DATA_RESOLVE: "SELECT_STREAM_PENDING", CHANGE_TRACK: "LOAD_TRACK_DATA", // Переход сюда НЕ отменит текущие эффекты по умолчанию }, SELECT_STREAM_PENDING: { SELECT_STREAM_RESOLVE: "SET_STREAM_PENDING", }, SET_STREAM_PENDING: {}, }, initialState: "IDLE", initialContext, reducer: (s, action, { nextState }) => { s.state = nextState; return s; }, effects: { LOAD_TRACK_DATA: ({ transition }) => { transition({ type: "LOAD_TRACK_DATA_STARTED", }); }, LOAD_TRACK_DATA_PENDING: createEffect({ type: "latest", // Использование опции "latest" включает автоматическую отмену эффекта effect: async ({ condition, transition }) => { // Здесь код продолжит выполняться даже после отмены, // но вызовы transition будут игнорироваться await someAsyncOperation(); transition({ type: "LOAD_TRACK_DATA_RESOLVE", // Этот вызов будет проигнорирован, если эффект отменен }); }, }), }, });

В этом примере, если автомат находится в состоянии LOAD_TRACK_DATA_PENDING и приходит событие CHANGE_TRACK, эффект будет отменен только потому, что мы указали type: "latest". Без указания этого параметра результаты всех эффектов будут обрабатываться независимо от смены состояния.

Типы эффектов и стратегии отмены

lite-fsm предоставляет два основных типа эффектов с разными стратегиями отмены:

1. Тип “latest”

Выполняется только последний вызов, предыдущие отменяются (transition-вызовы игнорируются):

const searchEffect = createEffect({ type: "latest", // необходимо явно указывать для активации отмены эффектов effect: async ({ transition }, { query }) => { const results = await api.search(query); transition({ type: "SEARCH_SUCCESS", payload: { results } }); }, });

2. Тип “every”

Выполняются все вызовы, без отмены (используется по умолчанию):

const logEffect = createEffect({ type: "every", // можно не указывать, так как это значение по умолчанию effect: async ({ services }, { event }) => { // Логирует каждое событие, без отмены await services.analytics.logEvent(event); }, });
Last updated on