Angular RxJS主题完成后自动关闭订阅
我在一个服务中公开了两个主题,因此我可以呈现主题中的值并在页面上呈现它们 其中一个主题正确接收信息,但第二个主题自动关闭订阅,我无法再检索数据 这是我的代码:Angular RxJS主题完成后自动关闭订阅,angular,rxjs,Angular,Rxjs,我在一个服务中公开了两个主题,因此我可以呈现主题中的值并在页面上呈现它们 其中一个主题正确接收信息,但第二个主题自动关闭订阅,我无法再检索数据 这是我的代码: // service.ts clientSubject: Subject<any>; jobSubject: Subject<any>; constructor(private clientService: ClientService, private jobService: JobService)
// service.ts
clientSubject: Subject<any>;
jobSubject: Subject<any>;
constructor(private clientService: ClientService, private jobService: JobService) {
this.clientSubject = new Subject();
this.jobSubject = new Subject();
}
fetchData(): void {
this.clientService.getClients()
.pipe(
map(clients => clients.map(
client => this.jobService.getJobs(client.clientId)
.pipe(
map(jobs => jobs.map(job => ({client, job})))
)
.subscribe(this.jobSubject)
)
))
.subscribe(this.clientSubject);
}
这是控制台记录的内容:
### this.jobs data ###
invoices.component.ts:25
[{…}]
0: {client: {…}, job: {…}}
length: 1
__proto__: Array(0)
### this.clients data ###
invoices.component.ts:19
(2) [SubjectSubscriber, SubjectSubscriber]
0: SubjectSubscriber {closed: true, _parentOrParents: null, _subscriptions: null, syncErrorValue: null, syncErrorThrown: false, …}
1: SubjectSubscriber {closed: true, _parentOrParents: null, _subscriptions: null, syncErrorValue: null, syncErrorThrown: false, …}
length: 2
__proto__: Array(0)
为什么基于fetchData
中的实现,SubjectSubscribers会覆盖this.clients
数据
jobService.getJobs(client.clientId)
返回以下格式的可观察值:
[{jobId: 1, name: 'blabla', items: []}]
[{clientId: 1, name: 'blabla', isParent: false}]
jobService.getClients()
返回具有以下格式的可观察对象:
[{jobId: 1, name: 'blabla', items: []}]
[{clientId: 1, name: 'blabla', isParent: false}]
现在。Map正在将客户端数组转换为订阅数组。这就是
clients.map([…]
)正在做的。可能让您困惑的是.subscribe
返回一个值?如下所示:
const valueReturnedBySubscribe = anyObservable.subscribe(LAMBDA);
console.log(valueReturnedBySubscribe);
输出:
SubjectSubscriber {closed: true, [...]
请尝试以下方法:
fetchData(): void {
this.clientService.getClients().pipe(
tap(clients => clients.forEach(
client => this.jobService.getJobs(client.clientId)
.pipe(
map(jobs => jobs.map(job => ({client, job})))
)
.subscribe(this.jobSubject)
)
)
)
.subscribe(this.clientSubject);
}
点击
根本不会更改您的流,而且您似乎也不需要订阅对象。不确定为什么要使用地图,但看起来您并不需要它
更新 让jobSubject订阅clientSubject可能最有意义,因为新客户端总是意味着查询新作业。这可能类似于:
clientSubject: Subject<any>;
jobSubject: Subject<any>;
constructor(private clientService: ClientService, private jobService: JobService) {
this.clientSubject = new Subject();
this.jobSubject = new Subject();
this.clientSubject.pipe(
map(clients => clients.map(
client => jobService.getJobs(client.clientId).pipe(
map(jobs => jobs.map(job => ({client, job})))
)
)),
mergeMap(jobs => merge(jobs))
).subscribe(this.jobSubject);
}
fetchData(): void {
this.clientService.getClients().subscribe(this.clientSubject);
}
及
这里有很多问题
映射(客户端…
返回订阅,该订阅随后被推送到this.clientSubject
getClients()
函数返回的数组会触发多个订阅。您可以使用forkJoin
函数并行触发多个观察值
switchMap
来链接可观察对象,而不是嵌套订阅
fetchData():void{
此.clientService.getClients()管道(
点击(clients=>this.clientSubject.next(clients)),//forkJoin(clients.map(client=>//jobs.map(job=>({client,job})))
)
)))
).订阅(
jobs=>this.jobSubject.next(作业)
);
}
一个区别是,jobSubject
现在将发出一个作业数组,其形式为[{client,job},{client,job},…]
更新:在每个源通知上发出
您可以使用点击
操作员的下一步
、错误
和完成
回调向相应的主题发出每个相应的通知
fetchData():void{
此.clientService.getClients()管道(
轻触({//this.clientSubject.next(clients),
error:error=>this.clientSubject.next(error),
complete:()=>this.clientSubject.complete()
}),
switchMap(clients=>forkJoin(clients.map(client=>//jobs.map(job=>({client,job}))),
水龙头({
next:jobs=>this.jobSubject.next(jobs),
error:error=>this.jobSubject.error(error),
complete:()=>this.jobSubject.complete()//与observable.subscribe(subject)
不同,这不会传递错误()
或完成()
发射到他的受试者身上。@MrkSef:我已经更新了答案,使用点击
来发射两个源观测到的相应类型的通知。是的,这总是一个很好的舞蹈:“我应该准确回答海报上的问题,还是应该回答我认为他们想问的问题?”-我想你是对的,他不希望他的受试者在一个可观测的源完成的那一刻完成。
this.clientService.getClients().subscribe(this.clientSubject);
to
this.clientService.getClients().subscribe(this.clientSubject.next);