简体   繁体   English

rxjs科目应该在课堂上公开吗?

[英]Should rxjs subjects be public in the class?

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. 第一个示例在某种程度上是不安全的,因为任何人都可以从类外调用eventsPub.endEvent.next()并引入副作用,但是,与示例2相比它允许管道,这是一个很大的优势,因为开发人员可以为ex。 register only for the first event with eventsPub.onEnd.pipe(first()).subscribe(cb) . 仅使用eventsPub.onEnd.pipe(first()).subscribe(cb)注册第一个事件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? 或者也许有更好的解决方案?

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. 所以在课堂上我会使用endEvent而我仍然可以使用它,例如。 in a template with obj.endEvent$ | async obj.endEvent$ | async的模板中 obj.endEvent$ | async and from the outside it behaves like an Observable. obj.endEvent$ | async和从外部它的行为就像一个Observable。

Note, that in fact I'm returning the same instance of Subject . 请注意,实际上我正在返回相同的Subject实例。 The only thing that restricts the outside world from misusing it with obj.endEvent$.next() are Typescript's type guards. 限制外部世界滥用obj.endEvent$.next()的唯一因素是Typescript的类型保护。 If I was using just JavaScript or if I typecasted it to any I could call next . 如果我只是使用JavaScript,或者我将其类型化为我next可以调用的any

This is actually the recommended way of exposing Subject s instead of using the asObservable() operator. 这实际上是暴露Subject的推荐方式,而不是使用asObservable()运算符。 You can notice that this is used everywhere internally in RxJS 5. For example if you look at repeatWhen synopsys: 您可以注意到这在RxJS 5内部随处使用。例如,如果您查看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 ). 您可以看到notifier函数接收Observable作为参数(您可以在此处的代码中看到它以及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 . 但是如果你查看调用函数的代码,你会发现它们实际上是传递了一个Subject而不是一个Observablehttps//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. 这已在RxJS GitHub页面上讨论过,其原因在于性能以及Typescript类型保护就足够了。 You can read more in these discussions: 您可以在以下讨论中阅读更多内容:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM