Subject and BehaviorSubject — for frameworks and UI libs
So far this proposal is evolving in an interesting way, but it appears to cater mostly for the "direct" use, in which developers call EventTarget.when from application code.
In the context of UI libraries and frameworks that want to support Observables there may be a few things that could turn very useful.
The issue is that we often need to subscribe to Observables that don't exist yet, when running as part of templates or UI components.
Take the following example, based on a usage pattern being currently pioneered by Rimmel.js:
import { BehaviorSubject, scan } from 'rxjs';
import { rml } from 'rimmel';
const Component = () => {
const count = new BehaviorSubject(0).pipe(
scan(x => x+1)
);
return rml`
<button onclick="${count}">click me</button> <br>
<button onclick="${count}">or me</button> <br>
Clicked <span>${count}</span> times.<br>
Yes, I repeat: you clicked it <span>${count}</span> times.<br>
`;
};
document.body.innerHTML = Component();
As you can see, in the component above we have a stream called count, which libraries like Rimmel can plug both ways to the DOM: on the input side to the event source, on the output side as sinks, back to the DOM.
It would be a bit challenging to implement the above without the use of Subject and/or BehaviorSubject, without magic constructs like "Forward Refs" (=proxies) and without sacrificing ergonomics (mainly) or performance (secondarily, because of proxies).
These two primitives both act as central points of reference in the data flow. If we think entirely in streams, we need to be able to connect them from multiple sources (e.g.: from two different buttons, like above), to multiple targets (again, two span tags like above). This way we can isolate side effects and leave them with the framework.
In the component code (which only runs once, before the component is rendered unlike in React where it runs for every update), as we don't yet have access to the observable coming from the DOM, we use this BehaviorSubject as a temporary connector.
I have a Stackblitz example that shows this in action.
Unfortunately, we can only go as far as connecting the native Observable to the BehaviorSubject, so RxJS has to take over the stream very quickly and developers can have little interaction (=none) with the original, native Observable:
[Event Target (onclick)] => [DOM Observable] => [Rx.BehaviorSubject (count)] => [ops] => [sink (innerHTML)]
That would leave little motivation to use DOM Observables. Thoughts? Can we not just have Subject and BehaviorSubject in the spec?
Perhaps what you are looking for is the Signals proposed on the language specification side. https://github.com/tc39/proposal-signals
No, that's exactly what I'm trying to steer clear of. Observables enable functional-reactive programming, whilst Signals are the antithesis of all this.