Перейти к содержанию

Отложенные (after) переходы

Отложенные переходы — это переходы, которые срабатывают после установленного промежутка времени. Отложенные переходы полезны для создания таймаутов и интервалов в логике вашего приложения. Если другое событие произойдёт до окончания таймера, переход не завершится.

Отложенные переходы определяются в свойстве after узла состояния, либо как число (измеряемое в миллисекундах), либо как строка, ссылающаяся на задержку, определённую в объекте delays настройки.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { createMachine } from 'xstate';

const pushTheButtonGame = createMachine({
    initial: 'waitingForButtonPush',
    states: {
        waitingForButtonPush: {
            after: {
                5000: {
                    target: 'timedOut',
                    actions: 'logThatYouGotTimedOut',
                },
            },
            on: {
                PUSH_BUTTON: {
                    actions: 'logSuccess',
                    target: 'success',
                },
            },
        },
        success: {},
        timedOut: {},
    },
});

Совет

Посмотрите наше видео "Delayed (after) transitions" на YouTube (1m17s).

Задержки

Вы можете определить задержки несколькими способами: встроенные, ссылочные и как выражение.

Встроенные задержки

Вы можете определить встроенную задержку, указав время задержки (в миллисекундах) напрямую:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const machine = createMachine({
    initial: 'idle',
    states: {
        idle: {
            after: {
                1000: { target: 'nextState' },
            },
        },
        nextState: {},
    },
});

Это выполнит переход в состояние nextState через 1000мс.

Ссылочные задержки

Вы также можете определить ссылочные задержки, указав строковый ключ задержки и предоставив фактическое время задержки отдельно.

Например:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import { setup } from 'xstate';

const machine = setup({
    delays: {
        timeout: 1000,
    },
}).createMachine({
    initial: 'idle',
    states: {
        idle: {
            after: {
                timeout: { target: 'nextState' },
            },
        },
        nextState: {},
    },
});

Динамические задержки

Задержки также могут быть динамически определены как функция, возвращающая время задержки в миллисекундах:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import { setup } from 'xstate';

const machine = setup({
    types: {
        context: {} as {
            attempts: number;
        },
    },
    delays: {
        timeout: ({ context }) => {
            return context.attempts * 1000;
        },
    },
}).createMachine({
    initial: 'attempting',
    states: {
        attempting: {
            after: {
                timeout: {
                    actions: assign({
                        attempts: ({ context }) =>
                            context.attempts + 1,
                    }),
                    target: 'attempting',
                },
            },
        },
        // ...
    },
});

Жизненный цикл

Таймеры отложенных переходов отменяются при выходе из состояния.

Тестирование

  • Симулированные часы

Отложенные переходы и TypeScript

TypeScript

XState v5 требует TypeScript версии 5.0 или выше.

Для лучших результатов используйте последнюю версию TypeScript. Подробнее о XState и TypeScript

Вы можете строго типизировать delays вашей машины, настроив задержки в функции setup():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import { setup } from 'xstate';

const machine = setup({
    delays: {
        shortTimeout: 1000,
        longTimeout: 5000,
        eventually: 10_000,
    },
}).createMachine({
    after: {
        shortTimeout: {
            /* ... */
        },
    },
});

Шпаргалка по отложенным переходам

Используйте нашу шпаргалку по отложенным переходам XState ниже для быстрого старта.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
createMachine({
    after: {
        DELAY: {
            /* ... */
        },
    },
}).provide({
    delays: {
        DELAY: 1000, // или выражение
    },
});

Комментарии