Mastering Async & Sync in Angular

Whether you’re working with signals, observables, or good ol’ DOM access, this concise guide breaks down the most common async/sync patterns in Angular — and when to use each.

If you’re tired of second-guessing whether to use a signal, resource, or Observable, this is your go-to reference.


1️⃣ DOM Tasks — No Reactivity Needed

🔧 Use when: You need to run code after the view has rendered.

afterNextRender(() => {
// Safe to access DOM or manipulate layout here
});

✅ Ideal for:

  • DOM measurements (e.g., offsetHeight)
  • Scroll adjustments
  • Imperative third-party libs

2️⃣ Read Signal Value — No Tracking

📥 Just want the value? Read it like a function.

const userId = signal(123);
console.log(userId()); // 123

✅ No tracking. No side effects. Just a plain read.


3️⃣ Async Streams — RxJS Style

🔁 Use Observables for continuous or multi-emission streams.

import { of } from 'rxjs';
const numbers$ = of([1, 2, 3]);

✅ Use when:

  • You’re in a legacy Angular app
  • Need stream operators (filter, mergeMap, etc.)
  • Handling WebSocket-like streams

📌 Remember: You’ll still need asyncPipe or subscriptions.


4️⃣ Reactive State — Angular Signals (Sync)

🟢 Writable Signal (Local State)

const count = signal(0);
count.set(count() + 1);

🔵 Computed Signal (Derived State)

const double = computed(() => count() * 2);

🔄 Linked Signal (Writable + Derived)

const name = signal('Ahmed');
const linked = linkedSignal({
get: () => name(),
set: val => name.set(val)
});

✅ Best for:

  • Reactive UI state
  • Performance-sensitive updates
  • Type-safe data flows

5️⃣ Async State — Signal + Resource APIs

🧪 Angular 20 makes async data feel synchronous in your templates.

📦 From a Promise

const user = resource(() => fetchUser());

📡 From an Observable

const data = rxResource(() => this.service.getData$());

🌍 From HttpClient (GET only)

const users = httpResource(() => this.http.get('/api/users'));

📝 Note: Resources are read-only — use services for POST, PATCH, etc.

✅ Use for:

  • Lazy loading user data
  • Declarative fetching in templates
  • One-shot HTTP GETs

6️⃣ Side Effects (Signals Only)

effect() — Watch Signal Changes

effect(() => {
console.log('Count changed:', count());
});

Runs immediately and reacts on every update.

🔄 afterRenderEffect() — Post-DOM Reaction

afterRenderEffect(() => {
// DOM has updated — safe to measure or apply styles
});

✅ Great for:

  • Layout calculations
  • Scroll handling
  • Animation triggers

🚀 Final Thoughts

Angular is heading toward a signal-first architecture — and it’s a good thing. You get:

✅ Cleaner state
✅ Smarter async flows
✅ Less boilerplate
✅ Predictable reactivity

Knowing when to use signals, observables, or resources is key to writing modern, maintainable Angular apps.


🔖 Quick Reference

Use CaseTool
Post-render DOM logicafterNextRender()
Read a signal oncemySignal()
Multi-emission streamsObservable
Reactive local statesignal()
Derived valuecomputed()
Async fetch (Promise)resource()
Async stream (Observable)rxResource()
Side effecteffect()
Post-render side effectafterRenderEffect()

Bookmark it.
🔁 Share with your team.
💬 Have a tip or pattern? Drop it in the comments — let’s level up together.

Leave a Comment

Your email address will not be published. Required fields are marked *