最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Should rxjs subjects be public in the class? - Stack Overflow

programmeradmin4浏览0评论

Let's say I have two classes, where you can observe over some observables.

First example, with public subject:

class EventsPub {
   public readonly onEnd = new Subject<void>();
}

Second example, with private subject and registering method:

class EventsPriv {
   private readonly endEvent = new Subject<void>();

   public onEnd(cb: () => void): Subscription {
       return this.endEvent.subscribe(cb);
   }
}

The first example is somehow unsafe because anyone can call eventsPub.endEvent.next() from outside the class and introduce side effects, however, comparing to example 2 It allows for pipes, which is a big plus since developers can for ex. register only for the first event with eventsPub.onEnd.pipe(first()).subscribe(cb).

The second example also allows for one-time subscription but requires more code and ugly unsubscribing.

const subscription = eventsPriv.onEnd(() => {
    // logic..
    subscription.unsubscribe()
});

From your point of view, which is the best way to go? Or maybe there is a better solution?

Let's say I have two classes, where you can observe over some observables.

First example, with public subject:

class EventsPub {
   public readonly onEnd = new Subject<void>();
}

Second example, with private subject and registering method:

class EventsPriv {
   private readonly endEvent = new Subject<void>();

   public onEnd(cb: () => void): Subscription {
       return this.endEvent.subscribe(cb);
   }
}

The first example is somehow unsafe because anyone can call eventsPub.endEvent.next() from outside the class and introduce side effects, however, comparing to example 2 It allows for pipes, which is a big plus since developers can for ex. register only for the first event with eventsPub.onEnd.pipe(first()).subscribe(cb).

The second example also allows for one-time subscription but requires more code and ugly unsubscribing.

const subscription = eventsPriv.onEnd(() => {
    // logic..
    subscription.unsubscribe()
});

From your point of view, which is the best way to go? Or maybe there is a better solution?

Share Improve this question edited Jan 26, 2018 at 8:02 martin 96.9k26 gold badges203 silver badges234 bronze badges asked Jan 25, 2018 at 17:06 Mariusz BeltowskiMariusz Beltowski 9986 silver badges20 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 26

This is based a lot on my personal preference but I'd do it like this:

class EventsPriv {
   private readonly endEvent = new Subject<void>();

   get endEvent$(): Observable<void> {
      return this.endEvent;
   }
}

So inside the class I'll use endEvent while I can still use it eg. in a template with obj.endEvent$ | async and from the outside it behaves like an Observable.

Note, that in fact I'm returning the same instance of Subject. The only thing that restricts the outside world from misusing it with obj.endEvent$.next() are Typescript's type guards. If I was using just JavaScript or if I typecasted it to any I could call next.

This is actually the recommended way of exposing Subjects instead of using the asObservable() operator. You can notice that this is used everywhere internally in RxJS 5. For example if you look at repeatWhen synopsys:

public repeatWhen(notifier: function(notifications: Observable): Observable): Observable

You can see that the notifier function receives an Observable as a parameter (you can see it in the code here as well https://github.com/ReactiveX/rxjs/blob/5.5.6/src/operators/repeatWhen.ts#L29).

But if you look into the code where the function is called you'll see they are in fact passing a Subject and not an Observable: https://github.com/ReactiveX/rxjs/blob/5.5.6/src/operators/repeatWhen.ts#L114-L115.

This has been discussed on RxJS GitHub page and reasons for this are performance and that the Typescript type guards are sufficient. You can read more in these discussions:

  • https://github.com/ReactiveX/rxjs/pull/2408

  • https://github.com/ReactiveX/rxjs/issues/2391

发布评论

评论列表(0)

  1. 暂无评论