Drenai
Drenai

Reputation: 12357

Rxjs throttleTime - do we need to use asObservable?

I have been using these two (pretty identical methods) of calling throttleTime, but I am unsure if thery are actually identical or not.

this.scrollSubject$ = new Subject<Event>();
this.scrollSubscription$ = this.scrollSubject$
                    .asObservable()
                    .throttleTime(400, undefined, { trailing: true })
                    .subscribe(event => this.throttledScrollHandler(event));

The same as above, but with asObservable

this.scrollSubscription$ = this.scrollSubject$
                .throttleTime(400, undefined, { trailing: true})
                .subscribe( event => this.throttledScrollHandler(event));

I forgot to add the asObservable on my second one, but it behaved in the same way, which was a surprise. Are these two methods the same?

I'm using Observables in Angular, but I don't think this is Angular specific

Upvotes: 1

Views: 259

Answers (1)

cartant
cartant

Reputation: 58400

The answer to the question in the title is: yes, if you want to ensure that the subject's next, error and complete methods cannot be called via the composed observable, you should use asObservable.

So the two snippets in the question are not the same.

Subject implements lift. This means that the observable returned from an operator is a Subject. So, unless asObservable is called, it will be possible for next, error or complete to be called on the composed observable.

const subject = new Rx.Subject();

const withoutAsObservable = subject
  .do(value => console.log(value));
console.log("withoutAsObservable is a subject:", withoutAsObservable instanceof Rx.Subject);

const withAsObservable = subject
  .asObservable()
  .do(value => console.log(value));
console.log("withAsObservable is a subject:", withAsObservable instanceof Rx.Subject);

subject.subscribe(
  value => console.log("subject value:", value),
  error => console.log("subject error:", error)
);
withoutAsObservable.next("some value");
withoutAsObservable.error(new Error("some error"));
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>

For more information on lift see this issue.


Regarding your comment on another answer:

I can call this.scrollSubscription$['next'](new Event('asdf'));, and throttledScrollHandler() will print out that event

Calling next on the Subscription calls the next method on the Subscriber that was created from the next function you passed to subscribe. It has nothing to so with the subject and is not equivalent to calling the subject's next method.

The implementation of subscribe calls toSubscriber and that subscriber is returned. Subscriber extends Subscription, but it also has a next method. And that's what you are calling.

Upvotes: 1

Related Questions