I'm writing a short decorator helper function to turn a class into an event listener
My problem is that the decorators will register the decorated method as a callback for incoming events, but the decorated method won't retain it's original this
context.
Main question how can I retain the this
context of the decorated method in this scenario?
Implementation:
export function EventHandler (topicKey: any): ClassDecorator {
return function (target: any) {
const subscriptions = Reflect.getMetadata('subscriptions', target.prototype)
const topic = Container.get<DomainTopicInterface>(topicKey)
topic.subscribe(event => {
if (subscriptions.length === 0) {
throw new Error(`Event received for '${target.constructor.name}' but no handlers defined`)
}
subscriptions.forEach((subscription: any) => {
subscription.callback(event) // <---- the this context is undefined
})
})
return target
}
}
export function Subscribe (targetClass: StaticDomainEvent<any>): MethodDecorator {
return function (target: Function, methodName: string, descriptor: TypedPropertyDescriptor<any>) {
let originalMethod = descriptor.value
let subscriptions = Reflect.getMetadata('subscriptions', target)
if (!subscriptions) { Reflect.defineMetadata('subscriptions', subscriptions = [], target) }
subscriptions.push({
methodName,
targetClass,
callback: originalMethod
})
}
}
Example usage:
@EventHandler(Infra.DOMAIN_TOPIC)
export class JobHandler {
constructor (
@Inject() private service: JobService
) {}
@Subscribe(JobCreated)
jobCreated (events: Observable<JobCreated>) {
console.log(this) // undefined
}
}