事件发射器
自 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
});