Hey Devs 👋
We’re back with another weekly RxJS exploration — and this time, we’re diving into an interesting and less commonly used concept: AsyncSubject
.
🔍 What is an AsyncSubject?
Unlike other types of Subjects in RxJS, an AsyncSubject
emits only the last value to its subscribers — and only when the subject completes.
Still confused? Don’t worry — let’s break it down step by step.
🧪 Basic Syntax
const subject = new AsyncSubject();
🧰 Use Case Example in Angular
In this example, we'll bind a value from a textarea, send it to the AsyncSubject
, and subscribe using the Angular async pipe.
🧩 HTML
<h3>AsyncSubject</h3>
<div class="text-wrapper">
<div class="text">
<textarea
class="textarea-modern"
[(ngModel)]="asyncSubjectText"
name="asyncSubject"
id="asyncSubject"
></textarea>
<div class="btn-container">
<button class="btn-ghost" (click)="sendAsyncSubject()">Send</button>
<button class="btn-ghost" (click)="completeAsyncSubject()">Complete</button>
<button class="btn-ghost" (click)="addAsyncSubject()">Add</button>
</div>
</div>
<div class="example">
<p>User Input:</p>
@for (data of asyncSubjectData(); track $index) {
<div class="card">
<div class="index">{{$index}}</div>
<div class="data">{{data | json}}</div>
</div>
}
<p>AsyncSubject Value:</p>
@for (item of asyncSubjectArray(); track $index) {
@let data = asyncSubject | async;
<div class="card">
<div class="index">{{$index}}</div>
<div class="data">{{data | json}}</div>
</div>
}
</div>
</div>
🧠 TypeScript
import { Component, model, OnInit, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AsyncSubject } from 'rxjs';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-rxjs-operator',
imports: [CommonModule, FormsModule],
templateUrl: './rxjs-operator.html',
styleUrl: './rxjs-operator.scss',
})
export class RxjsOperator implements OnInit {
asyncSubject = new AsyncSubject();
asyncSubjectArray = signal<number[]>([0]);
asyncSubjectText = model<string>('');
asyncSubjectData = signal<string[]>([]);
ngOnInit(): void {}
addAsyncSubject() {
this.asyncSubjectArray.update((prev) => [...prev, 1]);
}
sendAsyncSubject() {
this.asyncSubjectData.update((prev) => [...prev, this.asyncSubjectText()]);
this.asyncSubject.next(this.asyncSubjectText());
}
completeAsyncSubject() {
this.asyncSubject.complete();
}
}
✅ Case 1: Initial State
Just like a regular Subject, AsyncSubject
has no initial value. Before you send any data, subscribers receive null
.
✅ Case 2: Sending Multiple Values
When sending multiple values through AsyncSubject
, only the last value before calling .complete()
is emitted to subscribers.
We print both the user’s input and what the AsyncSubject
actually emits.
📌 Note: Once .complete()
is called, no further values are accepted or emitted.
✅ Case 3: Multiple Subscribers
You can have multiple subscribers at different times. If the AsyncSubject
is already completed, any new subscriber will immediately receive the last emitted value.
🧬 Under the Hood
Internally, AsyncSubject
extends Subject
, but overrides the next()
and complete()
methods.
export class AsyncSubject<T> extends Subject<T> {
next(value: T): void {
if (!this._closed) {
this._value = value;
this._hasValue = true;
}
}
complete(): void {
const { _hasValue, _value, _isComplete } = this;
if (!_isComplete) {
this._isComplete = true;
_hasValue && super.next(_value!);
super.complete();
}
}
}
When to Use AsyncSubject?
AsyncSubject is ideal when:
- You need to emit only the final result after some operation is done.
- You want to replicate Promise-like behavior using Observables.
- You want subscribers to get only the final output, no matter when they subscribe.
🏁 Conclusion
AsyncSubject
is powerful in scenarios where you care only about the final emitted value. Though used rarely, it’s an excellent fit for promise-style observables or final-state-only data sharing.
💬 Got questions or use cases you want to share? Drop a comment below! Let's discuss more Javascript magic. ✨
✍️ Author: Vetriselvan
👨💻 Frontend Developer | 💡 Code Enthusiast | 📚 Lifelong Learner | ✍️ Tech Blogger | 🌍 Freelance Developer
Top comments (0)