Глобальные переходы
Глобальные переходы позволяют определить события, которые могут обрабатываться независимо от текущего состояния автомата. Эта мощная функция особенно полезна для обработки общих событий, таких как ошибки, сброс состояния или глобальные действия пользователя.
Концепция глобальных переходов
В lite-fsm глобальные переходы реализуются с помощью специального символа "*", который указывает, что переход должен применяться ко всем состояниям.
Синтаксис определения глобальных переходов
Глобальные переходы определяются в конфигурации автомата с использованием символа "*" в качестве ключа:
import { createMachine } from "lite-fsm";
export const player = createMachine({
config: {
"*": {
CHANGE_TRACK: "LOAD_TRACK_DATA_PENDING",
},
IDLE: {
// Обычные переходы
},
LOAD_TRACK_DATA_PENDING: {
// Обычные переходы
},
SELECT_STREAM_PENDING: {
// Обычные переходы
},
SET_STREAM_PENDING: {
// Обычные переходы
},
},
initialState: "IDLE",
initialContext,
reducer: (s, action, { nextState }) => {
s.state = nextState;
return s;
},
effects: {},
});Приоритет переходов
При обработке событий lite-fsm проверяет переходы в следующем порядке:
- Специфичные переходы для текущего состояния
- Глобальные переходы (если специфичный переход не определен)
Это означает, что глобальные переходы могут быть переопределены в конкретных состояниях:
config: {
"*": {
RESET: "IDLE", // Применяется ко всем состояниям
ERROR: "ERROR_STATE", // Применяется ко всем состояниям, кроме тех, где переопределено
},
PLAYING: {
ERROR: "PLAYING_ERROR", // Переопределяет глобальный переход для состояния PLAYING
},
}Применение глобальных переходов
1. Общие действия, доступные в любом состоянии
const playerMachine = createMachine({
config: {
"*": {
CHANGE_TRACK: "PAUSED",
},
PAUSED: {
RESUME: "PLAYING",
},
PLAYING: {
PAUSE: "PAUSED",
},
// Другие состояния...
},
// ...
});2. Обработка ошибок на глобальном уровне
const appMachine = createMachine({
config: {
"*": {
NETWORK_ERROR: "ERROR",
FATAL_ERROR: "CRASHED",
},
IDLE: {
FETCH_DATA: "LOADING",
},
LOADING: {
DATA_LOADED: "DATA_READY",
},
DATA_READY: {
PROCESS_DATA: "PROCESSING",
},
PROCESSING: { },
},
// ...
});3. Сброс состояния
const formMachine = createMachine({
config: {
"*": {
RESET_FORM: "INITIAL", // Сброс формы из любого состояния
},
INITIAL: {
FIELD_CHANGE: "EDITING",
},
EDITING: {
SUBMIT: "VALIDATING",
},
VALIDATING: {
VALIDATION_SUCCESS: "SUBMITTING",
VALIDATION_ERROR: "INVALID",
},
INVALID: {
FIELD_CHANGE: "EDITING",
},
SUBMITTING: {
SUBMIT_SUCCESS: "SUCCESS",
SUBMIT_ERROR: "ERROR",
},
SUCCESS: {},
ERROR: {
RETRY: "SUBMITTING",
},
},
// ...
});Лучшие практики
- Используйте для общих операций: Глобальные переходы лучше всего подходят для действий, которые должны быть доступны из любого состояния.
- Избегайте избыточности: Не дублируйте один и тот же переход во всех состояниях, используйте глобальный переход.
- Переопределяйте где нужно: В состояниях, где поведение должно отличаться, переопределите глобальный переход.
- Документируйте глобальные события: Явно указывайте, какие события обрабатываются глобально, для лучшей поддерживаемости.
- Используйте для отладки: Глобальные переходы удобны для добавления отладочных действий во время разработки.
- Осторожно с глобальными переходами: Не злоупотребляйте ими, так как это усложняет контроль над логикой автомата. Используйте их в основном для сброса автомата в начальное состояние или для обработки критических ошибок.
Last updated on