Matt Mckeller
Matt Mckeller

Reputation: 43

Return subject only for subscription

my question is regarding returning a reference to a subject without allowing the receiver to do .next() on the subject.

For instance, I have a service which contains a subject and can trigger new events on the subject

class ExampleService {
  private exampleSubject = new Subject<boolean>;

  // Ideally the only way to call next on the subject
  doNext() {
    this.exampleSubject.next(true);
  }

  getSubject() {
    // Ideally returning a reference to the subject but only with the 
    // ability to subscribe and listen for events, not to call .next()
    return this.exampleSubject;
  }
}

Again, what I am looking for is a way to have other components call this service and get the subject but only be able to subscribe and listen for changes, they should not be able to make changes.

ExampleService.getSubject().subscribe(() => {
  //do something 
}) // ok
ExampleService.getSubject().next(true) // error/not allowed

Upvotes: 1

Views: 851

Answers (1)

martin
martin

Reputation: 96969

The officially recommended way of doing this (assuming you're using TypeScript) is to force retype the Subject to an Observable (Subject is Observable like any other):

class ExampleService {
  private exampleSubject = new Subject<boolean>();
  observable$: Observable<boolean> = this.exampleSubject;

  ...
}

Now observable$ can be public because it's just a regular Observable. TypeScript won't allow you to call eg ExampleService.observable$.next() because this method doesn't exist on Observables.

If you're using just JavaScript you can use exampleSubject.asObservable() to return Observable from a Subject.

This discussion on RxJS's GitHub is also relevant: https://github.com/ReactiveX/rxjs/pull/2408

Upvotes: 4

Related Questions