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

Финальные состояния

Финальное состояние — это состояние, которое представляет завершение или успешное окончание машины. Оно определяется свойством type: 'final' на узле состояния:

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

const feedbackMachine = createMachine({
    initial: 'prompt',
    states: {
        prompt: {
            /* ... */
        },
        thanks: {
            /* ... */
        },
        closed: {
            type: 'final',
        },
        // ...
    },
    on: {
        'feedback.close': {
            target: '.closed',
        },
    },
});

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

Машина может иметь несколько финальных состояний или не иметь финальных состояний.

  • Машина состояний может иметь ноль или более финальных состояний. Некоторые машины могут работать бесконечно и не нуждаться в завершении.
  • Финальные состояния могут иметь данные output, которые отправляются родительской машине при завершении машины.
  • Когда машина достигает финального состояния верхнего уровня, она завершается.
  • Финальные состояния не могут иметь переходов

Финальные состояния верхнего уровня

Финальное состояние верхнего уровня — это финальное состояние, которое является непосредственным дочерним состоянием машины. Когда машина достигает финального состояния верхнего уровня, машина завершается. Когда машина завершается, она больше не может получать события и переходить.

Дочерние финальные состояния

Когда достигается дочернее финальное состояние родительского (составного) состояния, это родительское состояние считается «завершённым». Переход onDone этого родительского состояния выполняется автоматически.

 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
31
32
33
34
35
import { createMachine } from 'xstate';

const coffeeMachine = createMachine({
    initial: 'preparation',
    states: {
        preparation: {
            initial: 'weighing',
            states: {
                weighing: {
                    on: {
                        weighed: {
                            target: 'grinding',
                        },
                    },
                },
                grinding: {
                    on: {
                        ground: 'ready',
                    },
                },
                // Дочернее финальное состояние родительского состояния 'preparation'
                ready: {
                    type: 'final',
                },
            },
            // Переход будет выполнен при достижении дочернего финального состояния
            onDone: {
                target: 'brewing',
            },
        },
        brewing: {
            // ...
        },
    },
});

Финальные состояния в параллельных состояниях

Когда все регионы параллельного состояния «завершены», параллельное состояние считается «завершённым». Выполняется переход onDone параллельного состояния.

В этом примере состояние preparation является параллельным состоянием с двумя регионами: beans и water. Когда оба региона завершены, состояние preparation завершено, и происходит вход в состояние brewing.

 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
31
32
33
34
35
36
37
38
39
40
41
import { createMachine, createActor } from 'xstate';

const coffeeMachine = createMachine({
    initial: 'preparation',
    states: {
        preparation: {
            type: 'parallel',
            states: {
                beans: {
                    initial: 'grinding',
                    states: {
                        grinding: {
                            on: {
                                grindingComplete: 'ground',
                            },
                        },
                        ground: {
                            type: 'final',
                        },
                    },
                },
                water: {
                    initial: 'heating',
                    states: {
                        heating: {
                            always: {
                                guard: 'waterBoiling',
                                target: 'heated',
                            },
                        },
                        heated: {
                            type: 'final',
                        },
                    },
                },
            },
            onDone: 'brewing',
        },
        brewing: {},
    },
});

Выходные данные

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

 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
31
32
import { createMachine, createActor } from 'xstate';

const currencyMachine = createMachine({
    // ...
    states: {
        converting: {
            // ...
        },
        converted: {
            type: 'final',
        },
    },
    output: ({ context }) => ({
        amount: context.amount,
        currency: context.currency,
    }),
});

const currencyActor = createActor(currencyMachine, {
    input: {
        amount: 10,
        fromCurrency: 'USD',
        toCurrency: 'EUR',
    },
});

currencyActor.subscribe({
    complete() {
        console.log(currencyActor.getSnapshot().output);
        // выводит, например, { amount: 12, currency: 'EUR' }
    },
});

Свойство .output также может быть статическим значением:

1
2
3
4
5
6
7
8
import { createMachine, createActor } from 'xstate';

const processMachine = createMachine({
    // ...
    output: {
        message: 'Process completed.',
    },
});

Шпаргалка по финальным состояниям

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

const feedbackMachine = createMachine({
    initial: 'prompt',
    states: {
        prompt: {
            /* ... */
        },
        thanks: {
            /* ... */
        },
        closed: {
            type: 'final',
        },
        // ...
    },
    on: {
        'feedback.close': {
            target: '.closed',
        },
    },
});

Шпаргалка: финальные состояния в параллельных состояниях

 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
31
32
33
34
35
36
37
38
39
40
41
import { createMachine } from 'xstate';

const coffeeMachine = createMachine({
    initial: 'preparation',
    states: {
        preparation: {
            type: 'parallel',
            states: {
                beans: {
                    initial: 'grinding',
                    states: {
                        grinding: {
                            on: {
                                grindingComplete: 'ground',
                            },
                        },
                        ground: {
                            type: 'final',
                        },
                    },
                },
                water: {
                    initial: 'heating',
                    states: {
                        heating: {
                            always: {
                                guard: 'waterBoiling',
                                target: 'heated',
                            },
                        },
                        heated: {
                            type: 'final',
                        },
                    },
                },
            },
            onDone: 'brewing',
        },
        brewing: {},
    },
});

Комментарии