Xstate的并行状态

121 阅读2分钟

在状态图中,并行状态(Parallel states)是具有多个子状态(也称为域)的状态,这些子状态同时处于活动状态。这与父状态(parent state)不同,父状态一次只有一个子状态处于活动状态。

并行状态具有以下特征:

  • 进入并行状态也将同时进入其所有域。
  • 退出并行状态也将同时退出其所有域。
  • 以并行状态接收的事件会被所有域同时接收和处理。

下面是一个音乐播放器示例,其并行状态由两个域组成,一个用于处理播放播放进度,另一个用于处理音量:

import { createMachine, assign } from 'xstate';

const playerMachine = createMachine({
  id: '播放器',
  type: 'parallel',
  states: {
    track: {
      initial: '暂停中',
      states: {
        paused: {
          on: { PLAY: '播放中' },
        },
        playing: {
          on: { STOP: '暂停中' },
        },
      },
    },
    volume: {
      initial: '正常音量',
      states: {
        normal: {
          on: { MUTE: '静音' },
        },
        muted: {
          on: { UNMUTE: '正常音量' },
        },
      },
    },
  },
});

上述代码将构造如下图的状态机,在Stately中查看

并行状态的值

并行状态的值是一个对象,具有其每个域的状态值。

使用下列代码打印上述音乐播放器的状态值,在打印的值中可以看到其中包含了两个子状态:进度track和音量volume的值。

const playerActor = createActor(playerMachine);
playerActor.start();

console.log(playerActor.getSnapshot().value);
// logs the object:
// {
//   track: '暂停中',
//   volume: '正常音量'
// }

并行的onDone转变

当并行状态的所有域都达到其最终状态时,将自动进行并行状态 onDone 的转变。

以下代码构造了一个煮咖啡的状态机。

import { createMachine } from "xstate";

export const machine = createMachine({
  id: "煮咖啡",
  initial: "preparing",
  states: {
    preparing: {
      states: {
        grindBeans: {
          initial: "磨豆子中",
          states: {
            grindingBeans: {
              on: {
                BEANS_GROUND: {
                  target: "磨好了",
                },
              },
            },
            beansGround: {
              type: "final",
            },
          },
        },
        boilWater: {
          initial: "烧开水中",
          states: {
            boilingWater: {
              on: {
                WATER_BOILED: {
                  target: "烧开了",
                },
              },
            },
            waterBoiled: {
              type: "final",
            },
          },
        },
      },
      type: "parallel",
      onDone: {
        target: "开始制作咖啡",
      },
    },
    makingCoffee: {},
  },
});

在下列的煮咖啡状态机中,当两个域都达到其最终状态时,即磨豆子域到达磨豆子.磨好了状态并且烧开水域到达烧开水.水烧开了状态时,上层状态将自动进行 onDone 的转变,进入开始制作咖啡状态。

状态机如下图所示,在Stately中查看

建模思路(待补充)

  • 避免在域之间进行状态转变
  • 用于分离可能相互影响的关注点(例如:同步)

小结

创建并行状态的模板

import { createMachine } from "xstate";

const machine = createMachine({
  // ...
  states: {
    type: 'parallel',
    states: {
      one: {/* ... */},
      two: {/* ... */},
      three: {/* ... */}
    },
    onDone: {
      // 在所有域都到达最终状态时会自动进行onDone转换
    }
  }
});