angular - 为什么使用 RxJS .asObservable() getter/factory 函数模式?

标签 angular typescript rxjs reactivex

在很多使用 RxJS 的代码库中,我似乎遇到了暴露私有(private) Subjects 的模式。如 Observables通过 getter或正常 getObservable()功能。我的问题不是为什么.asObservable()被使用,但为什么它看起来如此普遍地包含在一个 getter/工厂函数中?

asObservable() 包裹在 getter/工厂函数中

private readonly _engineInfo$ = new Subject<EngineInfo>();
get engineInfo$() { return this._engineInfo$.asObservable(); }

asObservable() 作为实例变量

private readonly _engineInfo$ = new Subject<EngineInfo>();
public engineInfo$ = this._engineInfo$.asObservable();

问题

  • 我的不理解是 .asObservable()创建一个新的 Observable每次订阅 Subject .还创建了 Observable很热,可以多次订阅。 为什么要创建 Observable 的多个匿名实例,(每个访问/订阅一个),而不是只有一个 Observable ,在所有观察者订阅的一个类/服务上访问?
  • 这是否有不明显的优势getter/factory function图案?
  • 可能是因为垃圾收集或测试/模拟优势?

  • 到目前为止,我在所有服务/类中使用第二个示例中的实例变量设置,一切似乎都按预期工作,也有多个观察者。

    最佳答案

    何时使用 Subject.prototype.asObservable()

    这样做的目的是为了防止从 API 中泄露主题的“观察者端”。基本上是为了在您不希望人们能够“下一步”进入结果可观察对象时防止抽象泄漏。

    您永远不想将一个 Subject 实例返回给调用上下文。这样做有点类似于返回一个 Deferred 对象而不是一个 promise;并且,它会使主题对意外和破坏性的使用开放。因此,当暴露一个 Subject 时,你可能希望首先将它转换为 Observable。

    为了让这个工作,我们可以使用 Rx.Observable.prototype.asObservable()实例方法。

    主题本身是热的/可共享的,它充当源 Observable 和许多观察者之间的桥梁/代理,使多个观察者可以共享相同的 Observable 执行。

    这种 getter/factory 函数模式有什么不明显的优势吗?
    不,完全不是,因为您正在创建一个新的 Observable,以这个 Subject 作为源,以将它从使用 Observable 的代码中隐藏起来。

    When to use asObservable() in rxjs?

    关于angular - 为什么使用 RxJS .asObservable() getter/factory 函数模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61288259/

    相关文章:

    html - Angular 9 : html select does respect value in model after click

    angular - 将 token 存储在浏览器 sessionStorage 中是一个好习惯吗?

    typescript 泛型 : infer type from the type of function arguments?

    angular - Firebase列表对象到Angular 2中的可观察数组

    angular - Rxjs - 条件可管道运算符

    javascript - 访问嵌套类方法

    node.js - 将 Angular 更新到版本 8 后出现错误

    reactjs - React、Typescript 和 Webpack 向页面添加 bundle.js 的问题

    javascript - 当 rxjs.race() 获胜时,其他可观察量会发生什么?

    javascript - 如何获取值在 Angular react 形式中更改的字段的 FormControlName