Skip to content

事件发射器

自 XState 版本 5.9.0 起

XState 中的状态机和其他类型的 actor 逻辑具有发射事件的能力。这允许外部事件处理程序接收特定事件的通知。

对于状态机,可以使用 emit(event) 动作创建器发射事件。

import { setup, emit } from 'xstate';

const machine = setup({
actions: {
emitEvent: emit({ type: 'notification' })
}
}).createMachine({
// ...
on: {
someEvent: {
actions: { type: 'emitEvent' }
}
}
});

const actor = createActor(machine);

actor.on('notification', (event) => {
console.log('Notification received!', event);
});

actor.start();

actor.send({ type: 'someEvent' });
// 日志:
// "Notification received!"
// { type: "notification" }

从 actor 逻辑中发射事件

对于 promise actors、transition actors、observable actors 和 callback actors,你可以使用参数中的 emit 方法来发射事件。

Promise actors

import { fromPromise } from 'xstate';

const logic = fromPromise(async ({ emit }) => {
// ...
emit({
type: 'emitted',
msg: 'hello'
});
// ...
});

转换 actors

import { fromTransition } from 'xstate';

const logic = fromTransition((state, event, { emit }) => {
// ...
emit({
type: 'emitted',
msg: 'hello'
});
// ...
return state;
}, {});

Observable actors

import { fromObservable } from 'xstate';

const logic = fromObservable(({ emit }) => {
// ...
emit({
type: 'emitted',
msg: 'hello'
});
// ...
});

回调 actors

import { fromCallback } from 'xstate';

const logic = fromCallback(({ emit }) => {
// ...
emit({
type: 'emitted',
msg: 'hello'
});
// ...
});

发射动作创建器

发射动作是一种特殊的动作,它从状态机逻辑中向任何外部事件处理程序“发射”一个事件。发射的事件可以是静态定义的,也可以是动态定义的:

import { setup, emit } from 'xstate';

const machine = setup({
actions: {
// 发射一个静态定义的事件
emitStaticEvent: emit({
type: 'someStaticEvent',
data: 42
}),

// 基于上下文发射一个动态定义的事件
emitDynamicEvent: emit(({ context }) => ({
type: 'someDynamicEvent',
data: context.someData
}))
}
}).createMachine({
// ...
on: {
someEvent: {
actions: [
{ type: 'emitStaticEvent' },
{ type: 'emitDynamicEvent' }
]
}
}
});

事件处理程序

你可以使用 actor.on(event, handler) 将事件处理程序附加到 actor 以监听发射的事件:

const someActor = createActor(someMachine);

someActor.on('someEvent', (emittedEvent) => {
// 处理发射的事件
console.log(emittedEvent);
});

someActor.start();

actor.on(…) 方法返回一个订阅对象。你可以调用 .unsubscribe() 来移除处理程序:

const someActor = createActor(someMachine);

const subscription = someActor.on('someEvent', (emittedEvent) => {
// 处理发射的事件
console.log(emittedEvent);
});

someActor.start();

// ...

// 停止监听事件
subscription.unsubscribe();

通配符事件处理程序

你可以通过监听通配符 '*' 来监听任何发射的事件:

const someActor = createActor(someMachine);

actor.on('*', (emitted) => {
console.log(emitted); // 任何发射的事件
});

发射的 emitted 事件将被类型化为可以从状态机发射的所有可能事件的联合类型。

TypeScript

你可以通过在 setup(…) 函数的 types.emitted 属性中定义发射事件的类型来强类型化发射的事件:

import { setup, emit, createActor } from 'xstate';

const machine = setup({
types: {
emitted: {} as
| { type: 'notification'; message: string; }
| { type: 'error'; error: Error; },
// ...
}
}).createMachine({
// ...
on: {
someEvent: {
actions: [
// 强类型化的发射事件
emit({ type: 'notification', message: 'Hello' })
]
}
}
});

const actor = createActor(machine);

// 强类型化的事件处理程序
actor.on('notification', (event) => {
console.log(event.message); // string
});