Rxjs:防止将数据推送到服务之外的主题

Posted

技术标签:

【中文标题】Rxjs:防止将数据推送到服务之外的主题【英文标题】:Rxjs : prevent pushing data to subjects from outisde the service 【发布时间】:2020-06-05 03:16:02 【问题描述】:
Within my anguular app , i ve this service :

@Injectable()
export class myService

  myBehaviouSubject= new BehaviorSubject("");


  setData()
     this.myBehaviouSubject.next("123");
  


在我的 app.component 内部,我能够获取该值,但我想将其 readonly 保留或仅在服务本身内部可编辑,我想防止从组件推送任何数据 (.next('DATA'))

    @Component(

    )
    export class AppComponent implements OnInit 

      constructor(public myService : MyService)  

    getData()
      // GET VALUE
      this.myService.myBehaviouSubject.value
    

    unwantedMethodToSetValue()
           // SET VALUE -> i want to prevent this
           this.myService.myBehaviouSubject.next("unwanted value")

    


建议?

【问题讨论】:

保护 .next() 的用例是什么?能否请您说明一下为什么这可能有用? 【参考方案1】:

您只能通过将 observable 内部服务声明为类的私有字段来保留它。

@Injectable()
export class myService 

  private myBehaviouSubject = new BehaviorSubject("");

  // Use this observable inside the app component class.
  myBehaviouSubjectObservable = myBehaviouSubject.asObservable();

  setData() 
    this.myBehaviouSubject.next("123");
  


@Component(

)
export class AppComponent implements OnInit 

  constructor(public myService: MyService) 

  getData() 
    // You can subscribe to observable and can get value here
    this.myService.myBehaviouSubjectObservable.subscribe((value) => 
      console.log(value);
    )
  

  unwantedMethodToSetValue() 
    // SET VALUE -> you cannot do this here now.
    this.myService.myBehaviouSubject.next("unwanted value")

  

【讨论】:

这并没有解决获取价值的问题,也不是可观察的,也不是直接的价值。 我已经用内联 cmets 中的完整描述更新了我的代码。请让我知道它是否解决了您的问题。 给对 asObservable 感兴趣的人的说明:***.com/a/36989035/6543507【参考方案2】:

传统答案:如果您将 Subject 作为可观察对象返回,则不允许 .next() 调用。

但在您的情况下,您还希望在不订阅的情况下直接访问当前值,因此您也可以为此添加一个 getter。

@Injectable()
export class myService

  private readonly myBehaviouSubject = new BehaviorSubject("");


  setData()
     this.myBehaviouSubject.next("123");
  
  public get myObservable$(): Observable<string>
    return this.myBehaviourSubject;
  
  public get currentValue(): string
    return this.myBehaviourSubject.value;
  


【讨论】:

asObservable 实际上是多余的,正如 TS 符号所告知的那样,结果是可观察的,因此没有 nextvalue 属性/功能【参考方案3】:

使用属性访问修饰符:

@Injectable()
export class MyService
  private myValueSubject: BehaviorSubject<string> = new BehaviorSubject<string>("");
  public readonly myValueObservable: Observable<string> = this.myValueSubject.asObservable();

  public setData() 
     this.myValueSubject.next("123");
  
  public getData(): string 
    return this.myValueSubject.value;
  

MyService 的实例没有可公开访问的主题。

我通常会尽量避免使用像getData 这样的方法,倾向于订阅相关的 observable。如果我发现自己编写了这些方法,那就是重新评估我的架构的警告标志。如果您只想存储一个值并使用方法获取/设置它,请使用普通的旧私有属性。如果您仅通过getData() 之类的方法获取值,则主题的整个目的都将失败。

查看 typescript 类的文档,其中讨论了访问修饰符:https://www.typescriptlang.org/docs/handbook/classes.html

【讨论】:

这实现了与我的答案相同的效果,只是您可以意外覆盖 myValueObservable。不确定这有什么额外贡献? @Boyen 好吧,我可能在您输入的同时开始输入这个。在你回答完一个问题并防止它出现类似的答案后,这种做法并不典型。不确定这有什么作用。 我不想保护任何东西。我只是想看看你的答案是否包含我没有的东西,或者我是否理解你的错误,让我们两个都学习。无需感到受到攻击和报复。 事实证明,我确实理解错了。它确实以不同的方式实现了与我完全相同的东西。我关于能够覆盖 myValueObservable 的声明不正确,因为它被标记为只读。你可以告诉我,而不是攻击我的优点。 我相信它不会,它只是返回键入为可观察对象的主题(这就是 Observable 所做的)。没有创建新实例【参考方案4】:

https://stackblitz.com/edit/angular-protected-rxjs-subject

在这个我希望能满足你需求的解决方案中:

注意没有订阅 获取手动处理的更新 属性“myBehaviourSubject”是私有的,只能访问 在“TestService”类中。

【讨论】:

.. 事实上,订阅自动获取数据对我来说似乎很重要

以上是关于Rxjs:防止将数据推送到服务之外的主题的主要内容,如果未能解决你的问题,请参考以下文章

防止 viewcontroller 被推送到 splitviewcontroller 两次

防止 Django SQLite db 在推送到 Heroku 时被覆盖

如何在 Angular 4 中推送到数组的 Observable? RxJS

sh 防止直接推送到主人

Git从composer.json保存部署令牌url,防止推送到repo

Angular/RxJS 6:如何防止重复的 HTTP 请求?