radman
radman

Reputation: 18555

Prevent rxjs Subject from completing

In the example code below testSubj is subscribed to twice to sourceSubj one of these through the take operator. What appears to happen is that when the take Observable completes, it causes testSubj to complete even though it still has an active subscription.

My question is, why is this the behaviour and is there a way of preventing the Subject from completing?

rxjs 6.4

import { Subject } from 'rxjs';
import { take } from 'rxjs/operators';

const sourceSubj = new Subject<string>();

const testSubj = new Subject<string>();
testSubj.subscribe({
  next: s => console.log(`next: ${s}`), 
  complete: () => console.log(`completed`)
});

sourceSubj.pipe( take(1) ).subscribe(testSubj);
sourceSubj.subscribe(testSubj);
sourceSubj.next('1');

Upvotes: 1

Views: 1266

Answers (2)

Kang Ming Chua
Kang Ming Chua

Reputation: 877

try to think of Subject as an object with state, once it completes, it just stopped doing its task

you should just use merge https://codesandbox.io/embed/rxjs-subject-cb86j?fontsize=14&hidenavigation=1&theme=dark

import { merge, Subject } from 'rxjs';
import { take } from 'rxjs/operators';

const sourceSubj = new Subject<string>();

const first = sourceSubj.pipe(take(1));
const subscription = merge(sourceSubj, first).subscribe({
  next: s => console.log(`next: ${s}`), 
  complete: () => console.log(`completed`)
});

sourceSubj.next('1');

Upvotes: 0

cartant
cartant

Reputation: 58400

It completes because its complete method is called when the observable returned by the take operator completes.

The subject is an observer and responds to next, error and complete notifications. If you only want to subscribe to next and error notifications, forward only those to the subject:

sourceSubj.pipe(take(1)).subscribe({
  next: value => testSubj.next(value),
  error: error => testSubj.error(error) 
});

Upvotes: 1

Related Questions