DEV Community

Habibur Rahman
Habibur Rahman

Posted on

Angular Data Handling: When to use `| async` and when to `.subscribe()` manually

 One of the most common questions I get is: "Should I use the Async Pipe or subscribe manually?"

The answer is: Use the Async Pipe whenever possible. Subscribe manually only when necessary.

Here is the breakdown of both approaches.

Approach 1: The Gold Standard (Async Pipe)

If you simply need to display data from an API on the screen, do not subscribe in your TypeScript file. Pass the stream directly to the template.

Why?

  • Automatic Cleanup: Angular handles the unsubscription.
  • Cleaner Code: No ngOnInit or ngOnDestroy needed.
  • OnPush Compatible: Works great with performance optimizations.
<div *ngIf="data$ | async as data">
  {{ data.title }}
</div>
Enter fullscreen mode Exit fullscreen mode

Approach 2: The "Kill Switch" (Manual Subscription)

Sometimes, you can't use the pipe. Maybe you need to assign the data to a local variable to modify it, or send it to an analytics service.

In this case, you must manage the memory yourself. The safest way is the takeUntil pattern.

export class MyComponent implements OnDestroy {
  // 1. The Signal: Create a Subject to act as the "killer"
  private destroy$ = new Subject<void>(); 

  constructor(private dataService: DataService) {}

  ngOnInit(): void {
    this.dataService.getData()
      // 2. The Guard: Keep stream alive UNTIL destroy$ emits
      .pipe(takeUntil(this.destroy$)) 
      .subscribe(response => {
        this.data = response;
        // Logic happens here (e.g. calculations, logging)
        this.calculateTotals(response);
      });
  }

  ngOnDestroy(): void {
    // 3. The Trigger: Signal the subject to complete
    this.destroy$.next(); 
    this.destroy$.complete();
  }
}
Enter fullscreen mode Exit fullscreen mode

Summary:

  • Displaying data? Async Pipe.
  • Processing logic? Manual Subscription + takeUntil.

Don't mix them up, and your app will run smooth as butter.

Top comments (0)