
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 Case | Tool |
---|---|
Post-render DOM logic | afterNextRender() |
Read a signal once | mySignal() |
Multi-emission streams | Observable |
Reactive local state | signal() |
Derived value | computed() |
Async fetch (Promise) | resource() |
Async stream (Observable) | rxResource() |
Side effect | effect() |
Post-render side effect | afterRenderEffect() |
✅ Bookmark it.
🔁 Share with your team.
💬 Have a tip or pattern? Drop it in the comments — let’s level up together.