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 符号所告知的那样,结果是可观察的,因此没有 next
或 value
属性/功能【参考方案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