Understanding the Difference Between Observer and Subscriber in RxJS
April 7, 2025 7:53 PM

When working with RxJS in Angular, you often encounter the terms Observer and Subscriber. While they are closely related, they serve different purposes in the context of observables. This article will help you understand the difference between the two and clarify why the observer in the new Observable() constructor is typed as Subscriber
.
What is an Observer?
An Observer is an object that defines how to handle the values, errors, and completion notifications emitted by an observable. It has three main methods:
next(value)
: Handles the emitted value.error(err)
: Handles any error emitted by the observable.complete()
: Handles the completion of the observable.
Example of an Observer:
The observer is passed to the subscribe()
method of an observable to listen for emissions.
What is a Subscriber?
A Subscriber is an advanced version of an Observer
. It extends the Observer
interface and adds additional functionality, such as managing the subscription lifecycle. When you create an observable using new Observable(), the observer parameter inside the constructor is actually a Subscriber
.
Why is it a Subscriber?
The Subscriber
provides:
- Observer Methods: It has
next
,error
, andcomplete
methods, just like anObserver
. - Subscription Management: It includes methods like
unsubscribe()
to manage the lifecycle of the subscription. - Internal Handling: RxJS uses the
Subscriber
internally to ensure safe emissions and manage cleanup
Key Difference Between Observer and Subscriber
Feature | Observer | Subscriber |
---|---|---|
Definition | Defines how to handle observable emissions. | Extends Observer and manages subscriptions. |
Methods | next , error , complete . | Includes next , error , complete , and unsubscribe . |
Usage | Passed to subscribe() to listen for emissions. | Used internally by RxJS to manage observable behavior. |
In new Observable() | Not directly used. | The observer parameter is actually a Subscriber . |
Why is the observer in new Observable() Typed as Subscriber
?
When you create an observable using new Observable(), the function you pass to the constructor receives a Subscriber
object. This is because RxJS internally wraps the Observer
in a Subscriber
to provide additional functionality, such as managing the subscription lifecycle.
In this example:
- The observer parameter is typed as
Subscriber<string>
. - You can use it like an
Observer
(e.g., callnext
,error
, orcomplete
), but it also has additional methods likeunsubscribe
.
Implementing the async validator
In your SignupComponent, you have the forbiddenEmails method, which creates a custom observable for asynchronous validation. Here’s how the observer (typed as Subscriber
) works in this context:
forbiddenEmails = (control: AbstractControl): Observable<{ isForbidden: boolean }> => {
return new Observable((observer: Subscriber<{isForbidden: boolean}>) => {
const forbiddenList = ['test@example.com', 'admin@example.com'];
const value = control.value;
setTimeout(() => {
if (forbiddenList.includes(value)) {
observer.next({ isForbidden: true }); // Emit validation error
} else {
observer.next({ isForbidden: false }); // Emit no error
}
observer.complete(); // Complete the observable
}, 1000); // Simulate async delay
});
};
How It Works:
- The observer parameter is a
Subscriber<{ isForbidden: boolean }>
object. - It emits validation results using observer.next().
- It signals the completion of the observable using observer.complete()
Overall summary:
- Observer: Defines how to handle values, errors, and completion notifications from an observable.
- Subscriber: Extends
Observer
and adds subscription management. It is used internally by RxJS. - In the new Observable() constructor, the observer parameter is actually a
Subscriber
, which provides additional functionality beyond a plainObserver
.
Creating a Plain Observable
Here’s a simple example of creating and using a plain Observable
import { Observable } from 'rxjs';
const plainObservable = new Observable<string>((observer) => {
// Emit a value
observer.next('Hello');
// Emit another value
observer.next('World');
// Complete the observable
observer.complete();
// Emit after completion (this won't be executed)
observer.next('This will not be logged');
});
// Subscribe to the observable
plainObservable.subscribe({
next: (value) => console.log(value), // Logs emitted values
error: (err) => console.error(err), // Logs errors
complete: () => console.log('Observable completed'), // Logs when completed
});
Creating the Observable:
- The new Observable() constructor takes a function with an
observer
parameter. - The
observer
object has three methods:next(value)
: Emits a value to the subscriber.error(err)
: Emits an error and terminates the observable.complete()
: Signals that the observable has completed.
- The new Observable() constructor takes a function with an
Subscribing to the Observable:
- Use the
subscribe()
method to listen to the observable. - Pass an object with
next
,error
, andcomplete
callbacks to handle emitted values, errors, and completion
- Use the
Comments