使用Subject Observable的Angular服务调用next()方法,组件订阅未能看到。
使用Subject Observable的Angular服务调用next()方法,组件订阅未能看到。
我想从Angular服务中检索一个更新的对象值(借款人)。我在服务中创建了一个RxJS的Subject
,这样多个组件就可以订阅它并获取更新的值。
当我通过组件中提供的服务订阅该Subject时,我发现即使从BorrowerService中调用.next()
,onNext()
函数参数也从未被调用。
如果我在BorrowerService类中订阅,我发现.next()
按预期工作。似乎在调用.next()
的Service类和组件之间,Subject是不同的实例,因此不能获取该订阅。
这是对Angular服务或Observables的理解上的错误吗?如何在Service中更新值并在Component中被动地获取更改,而无需知道何时调用.next()
?
borrower-report.component.ts
@Component({ ... providers: [BorrowerService] }) export class BorrowerReport { private borrower: Borrower; constructor(private borrowerService: BorrowerService) { this.borrowerService.borrowerChanged.subscribe(borrower => {this.borrower = borrower}); } }
borrower.service.ts
@Injectable() export class BorrowerService { public borrowerChanged: Subject= new Subject (); //event handler selectBorrower(borrower: Borrower) { this.borrowerChanged.next(borrower); } }
在上述代码中,出现了一个问题:当调用`BorrowerService`的`changeValue`方法时,`borrowerChanged`的`BehaviorSubject`被更新,但是在`BorrowerReportComponent`中对`borrowerChangedObservable`的订阅并没有接收到更新的值。
这个问题的出现原因是`borrowerChangedObservable`在`BorrowerReportComponent`中的订阅是在组件初始化时进行的,而此时`borrowerChanged`的`BehaviorSubject`已经被创建并且拥有了默认值。因此,当调用`changeValue`方法更新`borrowerChanged`时,`BorrowerReportComponent`并没有重新订阅,所以无法接收到更新的值。
解决这个问题的方法是,在`BorrowerReportComponent`中使用`ngOnChanges`生命周期钩子重新订阅`borrowerChangedObservable`。这样,每当`borrowerChanged`的值发生变化时,`BorrowerReportComponent`都会重新订阅并接收到更新的值。
修改后的代码如下:
import { Component, OnInit, OnDestroy } from '@angular/core'; import { BorrowerService } from './borrower.service'; import { Subscription } from 'rxjs'; @Component({ selector: 'app-borrower-report', templateUrl: './borrower-report.component.html', styleUrls: ['./borrower-report.component.css'] }) export class BorrowerReportComponent implements OnInit, OnDestroy { private subscription: Subscription; constructor(private borrowerService: BorrowerService) {} ngOnInit(): void { this.subscription = this.borrowerService.borrowerChangedObservable.subscribe((borrower) => { console.log(borrower); }); } ngOnDestroy(): void { this.subscription.unsubscribe(); } sendNewValueToBorrowerService(): void { this.borrowerService.changeValue('my new value'); } }
通过在`ngOnInit`生命周期钩子中订阅`borrowerChangedObservable`,并在`ngOnDestroy`生命周期钩子中取消订阅,确保了每当`borrowerChanged`的值发生变化时,`BorrowerReportComponent`都能接收到更新的值。
需要注意的是,在组件的模板中,需要添加一个按钮或其他触发器来调用`sendNewValueToBorrowerService`方法,以便测试更新值的功能。
最后,确保在相同的模块中将`BorrowerService`添加到`providers`数组中,将`BorrowerReportComponent`添加到`declarations`数组中,以便正确注入和使用服务。
问题的原因是服务的范围,并且没有提供服务。如果您希望这是一个单例服务(多个组件共享同一个服务实例),那么您需要在包含所有子组件的父模块中提供该服务。要确保路由,您需要在
app.module.ts
中添加这个。在模块中导入它,并像在组件中那样提供它作为服务(不过要从组件中删除它作为提供者,您只需要父模块提供它)。
然后,您可以像之前一样将服务导入到组件中,provider
将是父模块。基本思路是父模块将托管所有子组件的服务,因此所有子组件将接收到相同的服务实例(因此相同的值)。
额外说明:这个Stack Overflow回答提供了创建单例服务ApiService
的详细信息,并且应该作为一个可靠的指南。其他顶级答案也提供了很好的解释。
第二点说明:如果您希望从您的主题中获得推送更新,您也应该使用BehaviorSubject。对BehaviorSubject的订阅将自动更新,而对Subject的订阅必须手动调用。
这对我有帮助,服务被实例化了两次。谢谢!