My 2 cents. Personally I love them, I’ve been using this signalling paradigm extensively since ~2013 or so. C# has delegates, which are essentially Signals, but integrated at the syntax level.
For those that are too lazy to research on your own, a signal is an event bus, just like, say EventDispatcher
, the key difference is that it does not have an eventName
, because the bus is intended to carry only 1 type of an event ever.
At this point a lot of you would say
So it’s like
EventDispatcher
, but worse?
And that would be a fair point. But the fact that it can do less is actually a good thing. Since a typical event bus can carry all sort of events, you always have to reach for documentation to find out what events are available at all, and then you have to sanitize the result that you get, because every event type can potentially carry different data type.
For example, in HTML we have something like a <div>
, let’s say we want to handle 2 events on that, one for keyboard key stokes and one for mouse movements, we’d write something like:
const element = document.createElement('div');
element.addEventListener('keydown', event => {
// event is of type KeyboardEvent
});
element.addEventListener('mousemove', event => {
// event is of type MouseEvent
});
The language doesn’t help you differentiate here, and you don’t even know what event types are available unless you read the documentation. If you make a typo, say write “mosemove” instead of “mousemove”, you’d probably not spot it immediately and spend a while debugging. If you have a spell check in your IDE, maybe it will catch that. How about “mousemoved”? How about “mousemovement”?
With signals you don’t have such problems, here’s a rough equivalent with signals:
const signaling_element = {
/**
* @type {Signal<KeyboardEvent>}
*/
onKeyDown: new Signal(),
/**
* @type {Signal<MouseEvent>}
*/
onMouseMove: new Signal(),
};
signaling_element.onKeyDown.add( event => {
// event is of type KeyboardEvent
});
signaling_element.onMouseMove.add( event => {
// event is of type MouseEvent
});
Just like most people agree that static typing in a language is a good thing, and TypeScript became incredibly popular as a direct consequence of that, Signals are a typed event paradigm.
For reference, here’s my take on signals from meep:
And here’s a set of unit tests that show usage:
This code is a fair bit outdated, but all of the principles are still the same.
I don’t think that signals are the best solution in every situation, there are some cases where they are a very poor fit, but those situations are few and far between.