消息转换
消息格式
默认情况下,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
等监听器提供类型推断支持。