angularrxjsangular17angular-observableangular-signals

Difference between observable toSignal AND updating Signal value inside the subscribe of Observable


Are there any differences or advantages or proper way to do this?

Let's say I have an observable, I may receive it from backend call, a service or through a GUI event like scrolling event.

I have a property in the template that depends on that observable. I am planning to provide the value to that property through a signal.

So I want to transfer the value to that signal through my observable, whenever it receives a value.

I found two ways to provide value to a signal through an observable:-

  1. By modifying the value of the signal inside the subscribe method of the observable.
  2. By converting the observable to a signal and directly using that signal.

Minimal Example Demonstrating Both Ways:-

Example On Stackblitz

import { Component, EventEmitter, OnDestroy, OnInit, Signal, signal } from '@angular/core';
import { toSignal } from "@angular/core/rxjs-interop";

@Component({
  selector: 'app-app',
  standalone: true,
  imports: [],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent implements OnInit {

  // First Way
  nonToSignalButtonClick$ = new EventEmitter<number>();
  signalVar = signal<number>(-1);

  // Second Way
  toSignalButtonClick$ = new EventEmitter<number>();
  signalVarThroughToSignal = toSignal(this.toSignalButtonClick$, {initialValue: -1});

  ngOnInit() {
    // First Way
    this.nonToSignalButtonClick$.subscribe((v) => this.signalVar.update(initial => initial + v));
  }

  onDirectClick() {
    this.signalVar.update(initial => initial + 1);
  }

  // First Way
  onObservableClick() {
    this.nonToSignalButtonClick$.emit(1);
  }

  // Second Way
  onObservableToSignalClick() {
    this.toSignalButtonClick$.emit(this.signalVarThroughToSignal() + 1);
  }
}
<h1>{{ signalVar() }}</h1>

<button (click)="onDirectClick()">Direct Signal Incrase</button>

<hr />

<button (click)="onObservableClick()">Signal Increase Through Observable</button>

<hr />

<h1>Through toSignal: {{ signalVarThroughToSignal() }}</h1>

<button (click)="onObservableToSignalClick()">Signal Increase Through Observable converted to Signal</button>

Are there any advantages or differences between using one approach over the other? Thanks!


Solution

  • The advantages of subscribe are the availability of error, subscribe and next, which gives you fine grained control when an API fails.

    ...
    .subscribe({
        next: () => {},
        error: (err: any) => {alert(err.message);},
        complete: () => {},
    });
    

    Unlike signal which has only next action.

    But for this particular scenario (showing a value from API), the signal method is better because:

    1. Less code
    2. More readable
    3. No subscribe unsubscribe needed, signal handles it automatically (toSignal handles the unsubscription automatically)

    The opposite applies to subscribe.

    The cons are:

    1. We will not be able to handle error scenario, without adding more code, I know it's possible, but it's simpler with subscribe.