Skip to content

Actor Model

当你运行一个状态机时,它就变成了一个 actor:一个可以接收事件、发送事件并根据接收到的事件改变其行为的运行进程

Actor logic

Actor logic 是 actor 的逻辑"模型"(大脑、蓝图、DNA 等)。它描述了 actor 在接收到事件时应该如何改变行为。

类型用途
createMachine最强、最完整
fromPromise请求 / async

在 XState 中,actor 逻辑由实现 ActorLogic 接口的对象定义,其中包含诸如 .transition(...).getInitialSnapshot().getPersistedSnapshot() 等方法。这个对象告诉解释器当接收到事件时如何更新 actor 的内部状态以及要执行哪些效果(如果有)。

Receive eventsSend eventsSpawn actorsInputOutput
State machine actors
Promise actors

createMachine

您可以将 actor 逻辑描述为 状态机 。actor 可以做到:

  • 接收事件
  • 向其他 Actor 发送事件
  • 调用/生成子级 Actor
  • 发出其状态的快照
  • 当机器到达其顶层最终状态时输出一个值
ts
const toggleMachine = createMachine({
  id: "toggle",
  initial: "inactive",
  states: {
    inactive: {
      on: {
        toggle: "inactive",
      },
    },
    active: {
      on: {
        toggle: "active",
      },
    },
  },
});

const toggleActor = createActor(toggleMachine);

toggleActor.subscribe((snapshot) => {
  // snapshot is the machine's state
  console.log("state", snapshot.value);
  console.log("context", snapshot.context);
});
toggleActor.start();
// Logs 'inactive'
toggleActor.send({ type: "toggle" });
// Logs 'active'

fromPromise

Promise actor 逻辑由一个异步过程描述,该过程会在一段时间后解析(resolve)或拒绝(reject)。从 promise 逻辑创建的 actor("promise actors")可以:

  • 发出 promise 的解析值
  • 输出 promise 的解析值

向 promise actor 发送事件将不会产生任何效果。

ts
const promiseLogic = fromPromise(() => {
  return fetch("https://example.com/...").then((data) => data.json());
});

const promiseActor = createActor(promiseLogic);
promiseActor.subscribe((snapshot) => {
  console.log(snapshot);
});
promiseActor.start();
// => {
//   output: undefined,
//   status: 'active'
//   ...
// }

// After promise resolves
// => {
//   output: { ... },
//   status: 'done',
//   ...
// }

创建 Actor

你可以通过 createActor(actorLogic, options?) 创建一个 actor,它是某种 actor 逻辑的"活动"实例。createActor(...) 函数接受以下参数:

  • actorLogic: 用于创建 actor 的 actor logic
  • options(可选):actor 选项

当你通过 createActor(actorLogic) 从 actor 逻辑创建一个 actor 时,你隐式地创建了一个 actor 系统 ,其中创建的 actor 是根 actor。从这个根 actor 及其后代生成的所有 actor 都是该 actor 系统的一部分。actor 必须通过调用 actor.start() 来启动,这也会启动 actor 系统:

ts
import { createActor } from "xstate";
import { someActorLogic } from "./someActorLogic.ts";

const actor = createActor(someActorLogic);

actor.subscribe((snapshot) => {
  console.log(snapshot);
});

actor.start();

// Now the actor can receive events
actor.send({ type: "someEvent" });

您可以通过调用 actor.stop() 来停止根 actor,这也会停止该 actor 系统以及该系统中的所有 actor:

ts
// Stops the root actor, actor system, and actors in the system
actor.stop();

Actor 作为 Promise

您可以通过使用 toPromise(actor) 函数从任何 actor 创建一个 promise。当 actor 完成(snapshot.status === 'done')时,promise 将使用 actor 快照的 .output 解析,或者当 actor 出错(snapshot.status === 'error')时,promise 将使用 actor 快照的 .error 拒绝。

ts
import { createMachine, createActor, toPromise } from "xstate";

const machine = createMachine({
  // ...
  states: {
    // ...
    done: { type: "final" },
  },
  output: {
    count: 42,
  },
});

const actor = createActor(machine);
actor.start();

// Creates a promise that resolves with the actor's output
// or rejects with the actor's error
const output = await toPromise(actor);

console.log(output);
// => { count: 42 }

如果 actor 已经完成,promise 将立即使用 actor 的 snapshot.output 解析。如果 actor 已经出错,promise 将立即使用 actor 的 snapshot.error 拒绝。

嵌套的 Actor

在 XState 里“不是只有一个状态机”,事件必须知道“发给谁”。

ts
Parent Actor
├── Form Actor
├── Fetch Actor
└── Timer Actor

保证事件“只被一个 actor 消费”:

ts
send({ type: "RESET" }, { to: "form" }); //明确告诉状态机,不是给我自己的,是给actor的

Actor 的特点

  • 封装:一个 Actor 拥有自己内部的、封装的状态,该状态只能由 actor 自身更新。actor 可以选择在接收到消息时更新其内部状态,但不能被任何其他实体更新。

  • 消息异步传递:actor 间通过消息异步交互。

  • 并发与独立性:每个 actor 独立运行,可以并发处理(逻辑上并发)。

  • 生命周期与监督:actor 有启动、停止、失败等生命周期,常由上级管理。

  • 内部的 actor 状态不会在 actor 之间共享。actor 共享其内部状态的任何部分的唯一方法是:

    • 向其他 actor 发送事件
    • 或者发出快照,这些快照可以被视为发送给订阅者的隐式事件。
  • Actor 可以创建(生成/调用)新的 Actor。

Actor 的生命周期

Actor 的生命周期与其被托管的状态节点绑定(invoke)或独立(spawn)。

  • 创建/启动:进入某个 state,XState 创建 actor 实例并传入 input(如果有)。
  • 运行中(pending):actor 执行业务逻辑,可发送事件到父机或其他 actor(若设计允许)。
  • 完成 / 失败:actor 成功返回 → XState 发 done 事件;失败 → error 事件。
  • 停止/取消:离开 state(或被 supervisor 停止)时,XState 会 stop actor(不再处理其后续结果/事件)。

Actor 的通信模式

Actor 之间只能通过 event 进行通信。

  • 父 ← 子(onDone / onError / event.output):invoke 自动发送 done/error。
ts
{
  type: 'xstate.done.actor.getUser',
  output: user
}
  • 父 ↔ 子(send/to):父机可用 send(..., { to: actorId }) 直接向某 actor 发消息。

  • actor → 父机(sendBack):在 fromCallback 等可主动发送事件给父机。

  • actor ↔ actor(中介或路由):通过父机或专门的 router actor 转发消息。

Actor 的输入和输出

一个 Actor 实例的输入是可选的。

只有“会结束(complete)”的 actor,才可能产生 output,“返回值”只存在于 “完成(done)事件” 中。