Skip to content

Persistence

Actor可以持久化其内部状态并在之后恢复。

持久化

持久化指的是将参与者的状态存储在持久化存储中,例如 localStorage 或数据库。

在 XState 中,你可以通过 actor.getPersistedSnapshot() 获取要持久化的快照(状态),并通过 createActor(behavior, { snapshot: restoredState }).start() 恢复它:

ts
const persistedState = JSON.parse(localStorage.getItem('some-persisted-state'));

const actor = createActor(someLogic, {
  snapshot: persistedState,
});

actor.subscribe(() => {
  localStorage.setItem(
    'some-persisted-state',
    JSON.stringify(actor.getPersistedSnapshot()),
  );
});

// Actor will start at persisted state
actor.start();

恢复状态

恢复指的是从持久化存储中恢复参与者的状态。

您可以通过将持久化状态传递给 createActor(logic, { snapshot: restoredState }) 的第二个参数的 state 选项,将 actor 恢复到持久化状态:

ts
// Get persisted state
const restoredState = JSON.parse(localStorage.getItem('feedback'));

// Restore state
const feedbackActor = createActor(feedbackMachine, {
  snapshot: restoredState,
});

feedbackActor.start();

深度持久化

从 actor 中持久化和恢复状态是深层次的;所有被调用(invoked)和生成(spawned)的 actor 都将被递归地持久化和恢复。

ts
const feedbackMachine = createMachine({
  states: {
    form: {
      invoke: {
        id: 'form',       // 给这个子 actor 一个唯一 id
        src: formMachine, // 被调用的子状态机
      },
    },
  },
});

不仅 feedbackActor 会恢复,它的 formMachine 也会在持久化状态下被恢复。

resolveState 持久化

如果你只想持久化有限状态机 actor 的状态 value(以及可选的 context),你可以使用 machine.resolveState(...) 方法:

ts
import { someMachine } from './someMachine';

const restoredStateValue = localStorage.getItem('someState');
// Assume that this is "pending"

const resolvedState = someMachine.resolveState({
  value: restoredStateValue,
  // context: { ... }
});

// Restore the actor
const restoredActor = createActor(someMachine, {
  snapshot: resolvedState,
});

restoredActor.start();
  • 轻量:只持久化 valuecontext

  • 非递归:不会自动恢复 invoke 或 spawn 的子 actor。

事件溯源(Event Sourcing)

不存状态,而是存 导致状态变化的事件序列

恢复状态时,通过 重放这些事件 来重新构建状态机的状态。

优点:

  • 版本兼容性更好:状态机逻辑更新后,只要旧事件依然有效,就能正确恢复状态。
  • 可追溯操作历史:可以知道每一步是怎么变过来的。
  • 可调试:可以在不同时间点重放事件,查看状态演变过程。
ts
import { createActor } from 'xstate';

const events: any[] = [];

const someActor = createActor(someMachine, {
  inspect: (inspectionEvent) => {
    if (inspectionEvent.type === '@xstate.event') {
      // 只监听发给 root actor 的事件
      if (inspectionEvent.actorRef !== someActor) return;

      events.push(inspectionEvent.event);
    }
  },
});

someActor.start();

// 保存事件序列
localStorage.setItem('events', JSON.stringify(events));

// 恢复时
const restoredActor = createActor(someMachine).start();
const savedEvents = JSON.parse(localStorage.getItem('events') || '[]');

for (const event of savedEvents) {
  restoredActor.send(event);
}