Sub-RFC 4 for Angular Signals Sparks Interesting Discussion Started by RxJS Author Ben Lesh

The ongoing discussion on integrating Angular Signals with RxJS Observables, and the Angular team’s stance on the matter.

Daniel Glejzner
Bits and Pieces

--

Generated by MidJourney AI

Before we dive into the interesting discussion — it’s essential to know that everyone has the opportunity to actively participate and express their opinions on upcoming Angular modifications in public discussions under existing sub-RFCs. The focus here is sub-RFC 4.

What are Signals and sub-RFC4?

Quick intro on the whole topic of Angular Signals. In a nutshell, Signals are a new approach to reactivity in Angular, simplifying reactivity while simultaneously enabling fine-tuned control over component updates.

Sub-RFC 4 is taking on the important topic of interoperability with RxJS Observables, a fundamental way of how we manage reactivity in Angular applications today.

Signals and RxJS compatibility

Seamless compatibility with current RxJS-based applications and libraries is what Angular Signals aim for.

Sub-RFC 4 presents two innovative APIs, toObservable and toSignal, conversation between Observables and Signals. You can find them in @angular/core/rxjs-interop. Keep in mind it’s all work in progress.

toSignal

Convert an RxJS Observable to an Angular Signal using toSignal:

const counter: Signal<number> = toSignal(counter$);

Internally, toSignal subscribes to the supplied Observable and updates the returned Signal each time the Observable emits a value. The subscription is established immediately, and Angular will automatically unsubscribe when the context in which it was created is destroyed.

Initial value

Using toSignal, you can provide a default value to use if the Observable hasn’t emitted by the time the Signal is read:

const secondsObs = interval(5000);
const seconds = toSignal(secondsObs, {initialValue: 0});
effect(() => {
console.log(seconds());
});

Error and completion states

Signals function as value wrappers, notifying consumers when the value changes. Observables, however, have three types of notifications: next, error, and complete. When an Observer created by toSignal is notified of an error, it will throw the error the next time the Signal is read. To handle the error at the Signal usage point, you can employ catchError on the Observable side or computed on the Signal side.

Signals lack a “complete” concept, but you can represent the completion state using an alternative signal or the materialize operator.

toObservable

Signal to Observable? Use toObservable- it takes an Angular Signal and returns an Observable. It does this by creating an effect when the Observable is subscribed to, which takes values from the signal and streams them to subscribers.

const count: Observable<number> = toObservable(mySignal);

The Observable produced by toObservable uses an effect to send the next value. All values emitted by the toObservable Observable are delivered asynchronously.

If you want to get the first value synchronously, you can use the startWith operator:

const obs$ = toObservable(mySignal).pipe(startWith(mySignal()));

Lifecycle and Cleanup

When a toObservable Observable is subscribed, it creates an effect to monitor the signal, which exists until that subscriber unsubscribes.

This differs from toSignal, which automatically cleans up its subscription when the context in which it was created is destroyed.

If desired, it’s straightforward to tie the resulting Observable to the component’s lifecycle manually:

const myValue$ = toObservable(myValue).pipe(takeUntil(this.destroy$))
Generated by MidJourney AI

The Angular Signals and Observables Debate

Now to the more interesting part. The sub-RFC 4 proposal sparked a discussion about the possibilities of integrating Angular Signals with Observables. It all comes down to whether Angular Signals should adopt globally understood common interop points like Symbol.asyncIterator and Symbol.observable.

Ben Lesh on his vision

Ben Lesh thinks that making signals fit observable chains directly is a good idea, stating that Signals inherently possess a time dimension that makes them well-suited for this. By adopting common interop points, Angular Signals could achieve better compatibility across various platforms.

Alex Rickabaugh pointing out potential issues

However, Alex Rickabaugh mentions that the team has been thinking about this approach, explaining that Angular Signals have unique characteristics that make it challenging to safely read them during the change propagation phase.

Additionally, signals require an injection context, which could result in surprising and burdensome requirements when used inside Observable pipelines. Alex states that signals are not Observables, and converting between them should be an intentional operation to ensure a well-considered application architecture.

The Angular Team’s Stance

The Angular team remains firm in their decision not to implement InteropObservable or any Subscribable interface for Angular Signals. Although this means no immediate changes to the framework, the debate has undoubtedly generated valuable insights and raised important questions about the future of Angular Signals and Observables.

Generated by MidJourney AI

Stay informed

The Angular sub-RFC 4 debate highlights the challenges and considerations involved in enhancing Angular. As the community continues to explore these ideas — discussions like this are going to happen in the end resulting in a better final implementation. I believe it’s important to stay informed about such conversations and even participate if you feel like you have a valuable point to add to the discussion.

I hope you liked my article!

If you did you might also like what I am doing on Twitter. I am hosting live Twitter Spaces about Angular with GDEs & industry experts! You can participate live, ask your questions or watch replays in a form of short clips :)

If you are interested drop me a follow on Twitter @DanielGlejzner — would mean a lot :). Thank You!

--

--

Founder of Angular Space / Angular Architect / Microsoft MVP / Nx Champion 🏆 / @AngularWroclaw - Organizer / Angular Bros - Co-Founder