消息转换
消息格式
默认情况下,FastEvent监听器接收到的消息格式统一为FastEventMessage,大体如下:
ts
{
type:string
payload:any
meta?:any
}FastEventMessage消息包括:
type: 事件类型payload: 事件有效负载meta: 事件额外的元数据
ts
import { FastEvent } from 'fastevent';
const emitter = new FastEvent()
emitter.on('x',(message)=>{
type keys = keyof typeof message
})转换消息
FastEvent支持通过transform参数可以对监听器接收到的事件消息进行转换,让监听器中接收到不一样的格式。
ts
import { FastEvent,FastEventOptions } from 'fastevent';
// {<事件名称>:<消息有效负载payload类型>}
type CustomEvents = {
'click': { x: number; y: number }
'div/mousemove': boolean;
'div/scroll': number;
'div/focus': string;
};
const emitter = new FastEvent<CustomEvents>({
transform: (message) => {
if (['div/click', 'div/mousemove'].includes(message.type)) {
return message.payload;
}
return message as any
},
});
emitter.on('click',(message)=>{
// typeof message !== { x: number; y: number } ❌
})以上代码中,我们针对div/click、div/mousemove两种事件直接返回payload。
如此,在监听器订阅时可以接收到经transform转换后的消息,而不是默认的FastEventMessage。
类型推断
但是以上代码还存在一个问题,在emitter.on('click',(message)=>{....})的message的类型推断是错误的。
为提供友好的类型推断,需要在声明事件时,使用NotPayload对负载进行标识,表示事件类型中的值不是负载。
ts
import { FastEvent,FastEventOptions,NotPayload } from 'fastevent';
// {<事件名称>:<消息有效负载payload类型>}
type CustomEvents = {
'click': NotPayload<{ x: number; y: number }>
'div/mousemove': boolean;
'div/scroll': number;
'div/focus': string;
};
const emitter = new FastEvent<CustomEvents>({
transform: (message) => {
if (['div/click', 'div/mousemove'].includes(message.type)) {
return message.payload;
}
return message
},
});
emitter.on('div/focus',(message)=>{
message.type
message.payload
})
emitter.on('click',(message)=>{
// typeof message === { x: number; y: number } ✅
})也可以使用TransformedEvents来声明所有事件,如下:
ts
import { FastEvent,FastEventOptions,TransformedEvents } from 'fastevent';
// {<事件名称>:<消息有效负载payload类型>}
type CustomEvents = TransformedEvents<{
'click': { x: number; y: number }
'div/mousemove': boolean;
'div/scroll': number;
'div/focus': string;
}>
const emitter = new FastEvent<CustomEvents>({
transform: (message) => {
return message.payload;
},
});
emitter.on('div/focus',(message)=>{ })
emitter.on('click',(message)=>{ })
emitter.on('div/scroll',(message)=>{ })
emitter.on('div/mousemove',(message)=>{ })作用域
FastEvent支持为每个scope方法单独指定transform。
ts
import { FastEvent,FastEventScope,TransformedEvents } from 'fastevent';
type CustomEvents = TransformedEvents<{
'client/connect': number;
'client/disconnect': number;
}>;
const emitter = new FastEvent();
class MyScope extends FastEventScope<CustomEvents> {
constructor() {
super(
Object.assign(
{
transform: (message:any) => {
return message.payload;
},
},
arguments[0],
),
);
}
}
const scope = emitter.scope('div', new MyScope());
// 或者 scope.options.transform=(message)=>{}
scope.on('client/connect', (message) => {
});
scope.emit('client/connect', 100);通配符
消息转换时的类型推断还支持通配符。
ts
import { FastEvent,FastEventOptions,TransformedEvents } from 'fastevent';
// {<事件名称>:<消息有效负载payload类型>}
type CustomEvents = TransformedEvents<{
'div/*/click': { id:String }
'div/*/mousemove': { x: number; y: number } ;
}>
const emitter = new FastEvent<CustomEvents>({
transform: (message) => {
return message.payload;
},
});
const scope = emitter.scope('div')
scope.on('x/click',(message)=>{
// typeof message === { id:string }
})
scope.on('y/mousemove',(message)=>{
// typeof message === { x: number; y: number }
})提示
transform用于将标准的 FastEventMessage 转换为你需要的格式NotPayload和TransformedEvents用于声明类型,为on/once等监听器提供类型推断支持。