转发订阅
FastEvent
支持转发订阅,将发布和订阅转发到另外一个FastEvent
实例。
转发订阅
转发订阅指的是将订阅转发到另外一个FastEvent
实例。
实现此功能需要使用Hook API onAddListener
,当调用on/once/anAny
订阅方法时,会调用该HOOK
。
该HOOK
可以通过返回false
来阻止订阅,也可以直接向其他FastEvent
实例订阅。
对订阅者而言,订阅者并不知道订阅是否被转发。
为了实现订阅转发,一般需要制定转发订阅的规则,比如:当事件名称以@/
开头时,将订阅转发到另外一个FastEvent
实例。
ts
const otherEmitter = new FastEvent()
const emitter = new FastEvent({
onAddListener: (type, listener, options) => {
// 订阅转发规则:当事件名称以`@/`开头时,将订阅转发到另外一个`FastEvent`实例
if (type.startsWith('@/')) {
return otherEmitter.on(type.substring(2), listener, options)
}
}
})
// 订阅data事件
emitter.on("@/data", ({ payload }) => {
return 1
})
emitter.on("@/data", ({ payload }) => {
return 2
})
// 发布data事件
otherEmitter.emit("data", 1)
otherEmitter.on
返回的是一个FastEventSubscriber
对象,可以通过off
方法取消订阅。在onAddListener
中可以直接返回给订阅者用于取消。
转发发布
也可以在当前FastEvent
实例直接订阅另外一个FastEvent
的事件。
实现此功能需要使用Hook API onBeforeExecuteListener
,该HOOK
会在执行emit
时被调用。
ts
const otherEmitter = new FastEvent()
const emitter = new FastEvent({
onBeforeExecuteListener: (message, args) => {
// 事件转发规则:当事件名称以`@/`开头时,就发布到其他`FastEvent`实例
if (message.type.startsWith('@/')) {
// 将事件名称从`@/`开始截取
message.type = message.type.substring(2)
return otherEmitter.emit(message, args)
}
}
})
otherEmitter.on("data", ({ payload }) => {
return 1
})
otherEmitter.on("data", ({ payload }) => {
return 2
})
const results = emitter.emit("@/data", 1)
// results = [[1,2]] ❌错误
- 以上代码中,当
emitter.emit
发布事件时,如果事件名称以@/开头
,则将消息转发到otherEmitter
。 - 预期
emit
方法应该返回的是所有订阅者监听器的结果数组:[1,2]
,但是实际上得到了是[[1,2]]
。这与预期不相符,为了解决此问题,需要使用expandable
对otherEmitter.emit
返回值进行包装,以便对返回的数组结果进行展开,这样可以确保返回结果的一致性。
ts
import { expandable } from "fastevent"
const otherEmitter = new FastEvent()
const emitter = new FastEvent({
onBeforeExecuteListener: (message, args) => {
// 事件转发规则:当事件名称以`@/`开头时,就发布到其他`FastEvent`实例
if (message.type.startsWith('@/')) {
// 将事件名称从`@/`开始截取
message.type = message.type.substring(2)
return expandable(otherEmitter.emit(message, args))
}
}
})
otherEmitter.on("data", ({ payload }) => {
return 1
})
otherEmitter.on("data", ({ payload }) => {
return 2
})
const results = emitter.emit("@/data", 1)
// results = [1,2]✅
重点
需要使用expandable
对otherEmitter.emit
返回值进行包装,以便对返回的数组结果进行展开,这样可以确保返回结果的一致性。