Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the point of AsyncSubject in RXJS?

The documentation for RxJS defines AsyncSubject as follows:

The AsyncSubject is a variant where only the last value of the Observable execution is sent to its observers, and only when the execution completes.

I don't see where / why I would ever need to use this variant of subject. Can someone provide an explanation or a real-world example to illustrate why it exists and its advantages?

like image 522
Code Whisperer Avatar asked Jan 17 '18 17:01

Code Whisperer


People also ask

What is AsyncSubject?

AsyncSubject is a variant of a Subject which keeps the last value emitted by a source observable before completion and sends it to all new subscriptions.

Why use subject instead of observable?

In comparison to a regular Observable, a Subject allows values to be multicasted to many Observers. A Subject and its subscribers have a one-to-many relationship. A Subject can be an Observable as well as an Observer. They hold a registry of many listeners to multiple Observables.

How does replay subject work?

The ReplaySubject is comparable to the BehaviorSubject in the way that it can send “old” values to new subscribers. It however has the extra characteristic that it can record a part of the observable execution and therefore store multiple old values and “replay” them to new subscribers.

Why do we use subject in angular?

Subject adds them to its collection observers. Whenever there is a value in the stream it notifies all of its Observers. The Subject also implements the next , error & complete methods. Hence it can subscribe to another observable and receive values from it.


2 Answers

It looks like it could be useful for fetching and caching (one-shot) resources, since generally http.get will emit one response then complete.

From rxjs/spec/subjects/AsyncSubject-spec.ts

it('should emit the last value when complete', () => {
it('should emit the last value when subscribing after complete', () => {
it('should keep emitting the last value to subsequent subscriptions', () => {

Components that subscribe after the fetch will then pick up value, which is not the case for Subject

const subject = new Rx.Subject();
const asyncSubject = new Rx.AsyncSubject();

// Subscribe before
subject.subscribe(x => console.log('before complete - subject', x))
asyncSubject.subscribe(x => console.log('before complete - asyncSubject', x))

subject.next('value 1');
subject.complete();
subject.next('value 2');

asyncSubject.next('value 1');
asyncSubject.complete();
asyncSubject.next('value 2');

// Subscribe after
subject.subscribe(x => console.log('after complete - subject', x))
asyncSubject.subscribe(x => console.log('after complete - asyncSubject', x))
.as-console-wrapper { max-height: 100% ! important; top: 0 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.js"></script>
like image 110
Richard Matsen Avatar answered Nov 10 '22 20:11

Richard Matsen


Cool!

And just for fun, I added handlers to log complete events to show they are raised in either case (Subject or AsyncSubject) when a subscribe happens after a subject is completed.

Also added BehaviorSubject.

const subject = new Rx.Subject();
const asyncSubject = new Rx.AsyncSubject();
const behaviorSubject = new Rx.BehaviorSubject();

console.log('before init - behaviorSubject', behaviorSubject.value)

subject.next('INIT');
asyncSubject.next('INIT');
behaviorSubject.next('INIT');

console.log('before subscribe - behaviorSubject', behaviorSubject.value)

// Subscribe before
subject.subscribe(x => console.log('before complete - subject', x))
asyncSubject.subscribe(x => console.log('before complete - asyncSubject', x))
behaviorSubject.subscribe(x => console.log('before complete - behaviorSubject', x))

subject.next('NEXT');
subject.complete();

asyncSubject.next('NEXT');
asyncSubject.complete();

behaviorSubject.next('NEXT');
behaviorSubject.complete();

// Subscribe after
subject.subscribe({
  next: x => console.log('after complete - subject', x),
  complete: () => console.log('after complete - subject COMPLETE')
})
asyncSubject.subscribe({
  next: x => console.log('after complete - asyncSubject', x),
  complete: () => console.log('after complete - asyncSubject COMPLETE')
})
behaviorSubject.subscribe({
  next: x => console.log('after complete - behaviorSubject', x),
  complete: () => console.log('after complete - behaviorSubject COMPLETE')
})
.as-console-wrapper { max-height: 100% ! important; top: 0 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.js"></script>
like image 44
Christopher King Avatar answered Nov 10 '22 20:11

Christopher King