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

Иерархические узлы состояния

В диаграммах состояний состояния могут быть вложены в другие состояния. Эти вложенные состояния называются составными состояниями (compound states).

API

Следующий пример — конечный автомат светофора с вложенными состояниями:

 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
42
43
44
const pedestrianStates = {
  initial: 'walk',
  states: {
    walk: {
      on: {
        PED_COUNTDOWN: { target: 'wait' },
      },
    },
    wait: {
      on: {
        PED_COUNTDOWN: { target: 'stop' },
      },
    },
    stop: {},
    blinking: {},
  },
};

const lightMachine = createMachine({
  key: 'light',
  initial: 'green',
  states: {
    green: {
      on: {
        TIMER: { target: 'yellow' },
      },
    },
    yellow: {
      on: {
        TIMER: { target: 'red' },
      },
    },
    red: {
      on: {
        TIMER: { target: 'green' },
      },
      ...pedestrianStates,
    },
  },
  on: {
    POWER_OUTAGE: { target: '.red.blinking' },
    POWER_RESTORED: { target: '.red' },
  },
});

'green' и 'yellow' состояния — это простые состояния (simple states) — у них нет дочерних состояний. Напротив, 'red' состояние является составным состоянием (compound state), поскольку оно состоит из подсостояний (substates) pedestrianStates.

Начальные состояния

Когда вводится составное состояние, сразу же вводится и его начальное состояние. В следующем примере светофора:

  1. переход в состояние 'red'
  2. поскольку 'red' имеет начальное состояние 'walk', то переходим в состояние { red: 'walk' }.
1
2
3
4
5
6
console.log(
  lightMachine.transition('yellow', { type: 'TIMER' }).value
);
// => {
//   red: 'walk'
// }

События

Когда простое состояние не обрабатывает event, это event распространяется до своего родительского состояния для обработки. В следующем примере светофора:

  1. состояние {red: 'stop'} не обрабатывает событие 'TIMER'
  2. событие 'TIMER' отправляется в 'red' родительское состояние, которое обрабатывает событие.
1
2
3
4
5
6
7
console.log(
  lightMachine.transition(
    { red: 'stop' },
    { type: 'TIMER' }
  ).value
);
// => 'green'

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

1
2
3
4
5
console.log(
  lightMachine.transition('green', { type: 'UNKNOWN' })
    .value
);
// => 'green'

Комментарии