Recently I was thinking about how Angular uses the awesome library RxJS, and specifically when observable objects are created and expected.
One of them is the EventEmitter
class that's used solely for emitting custom events in @Output
-decorated properties, like this:
@Component({ ... })
class MyTab {
@Output() selected = new EventEmitter<void>();
...
}
But what are EventEmitter
s? Why are they used for @Output
properties only? What do they add to the mix?
It turns out that the class EventEmitter
, as of Angular 11.2.3, extends RxJS' Subject
, adding just two things to the mix:
- an
emit
method that internally just callssuper.next
; - an optional, less-known constructor argument
isAsync
(defaulting tofalse
), that schedules the event emission on a subsequent task upon subscription (using the plain oldsetTimeout
).
That's it. EventEmitter
s don't automatically complete when the view is destroyed (that would be great, IMO). They don't do anything special, but the async option could be useful somewhere else, right?
But digging a little deeper, it looks like the Angular team initially designed EventEmitter
to be an extension of Subject
out of... convenience? And had something else in mind that could probably not involve observables at all. That's why Ward Bell stated you shouldn't use EventEmitter
s for anything else than @Output
properties, and none should pipe
them or subscribe
to them.
But... that comment is five years old. And nothing has changed since then. EventEmitter
still extends Subject
, and I know for a fact that there's code in production that explicitly subscribes to EventEmitter
s, or that uses simpler observables for @Output
properties. And now the fact that EventEmitter
extends Subject
is also explictly mentioned in the official documentation.
I think the Angular team should set this in stone and call it a day. I see no reason to change the observable nature of Angular's custom events.
Maybe I'm missing something here, and anything can change in the future. For the time being, I'll still refrain from using EventEmitter
s for anything that they're not supposed to be used for, just in case. (Also because they don't actually add much. And the class name is pretty specific, and misleading if not used for... emitting events, duh.)
But coding @Output
properties that are not EventEmitter
s... eh, that could actually be useful and simplify some code. With caveats.
Top comments (0)