An observable represents a stream that can emit values over time. In Angular, RxJS observables carry asynchronous results and framework events, but they also commonly represent shared state that changes over time. HttpClient returns observables, EventEmitter is built on them, and AsyncPipe can consume them in templates. section 5.2
Expose state as an observable when consumers should react to changes without being allowed to update the source directly. A service can keep a BehaviorSubject private to its own update logic, then return its read-only observable view with asObservable(). This avoids handing every component the full service API when it only needs one piece of state. section 3.2.2
Build and reshape streams with RxJS functions and operators:
- Create a predictable stream with of(1, 2, 3), which emits each supplied value in order. section 5.4.1
- Combine sources with merge(), which emits whenever any input observable emits. section 5.4.1
- Transform every emitted value with map(); mapping 1, 2, 3 by x => x * 10 produces 10, 20, 30. section 5.4.1
- Use observables for asynchronous HTTP work, reactive-form valueChanges, and events shared between application parts. section 5.2
Share authentication state without exposing mutations
An AuthService updates an isAuth$ BehaviorSubject after login and logout requests. A small injected isAuth() function returns isAuth$.asObservable(), allowing a footer to bind the result through AsyncPipe without directly calling next() on the subject. The pattern keeps state updates centralized while making a narrow reactive dependency easy to reuse. section 3.2.2
Listing 3.4 Showing user’s authentication status
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
export class AuthService {
private readonly http = inject(HttpClient);
isAuth$ = new BehaviorSubject(false); #1
login(credentials: { email: string, password: string }) {
return this.http.post('/api/auth/login', credentials).pipe(
tap(() => this.isAuth$.next(true)), #2
);
}
logout() {
return this.http.post('/api/auth/logout', {}).pipe(
tap(() => this.isAuth$.next(false)) , #3
);
}
}
This service shows the writable BehaviorSubject at the state boundary and login/logout side effects that publish authentication changes. section 3.2.2
Observables remain useful alongside signals: signals provide synchronous reactive state, while observables handle asynchronous streams of events. Convert a signal with toObservable when it must join an existing RxJS stream; the derived observable emits when the signal changes. Because the bridge uses an effect, it requires an injection context, and signal updates reach observable subscribers asynchronously after the current synchronous work finishes. section 6.6 section 6.6.2
A practical division is to model user actions such as approving, rejecting, or deleting a request as observable events, then derive the current request collection as signal state. This keeps event composition in RxJS while leaving components with a compact state-focused interface. section 7.3.4




