Angular 4 - rxjs BehaviorSubject 在服务中的使用

Angular 4 - rxjs BehaviorSubject usage in Service

我的服务代码如下所示 -

数据服务

@Injectable()
export class DataService {
...
private serviceRequestDtoSource = new BehaviorSubject<ServiceRequestDto>(null);
serviceRequestDto$ = this.serviceRequestDtoSource.asObservable();
...
getAccountInfo(serviceRequestDto : ServiceRequestDto){
    let body = JSON.stringify(serviceRequestDto);
    let headers = new Headers({
        'Content-Type': 'application/json'
    });
    let options = new RequestOptions({ headers: headers });
    console.log("In data service.getAccountInfo");
    this.http
        .post(this.clientAccountInfoURL, body, options)
        .map((response : Response) => { return <AccountDto[]> response.json().accountDtoList})
        .do(data=> console.log('All :'+ JSON.stringify(data)))
        .subscribe( response => { 
                             this.accountList = response; 
                             this.serviceRequestDto.accountDtoList = this.accountList;
                             this.serviceRequestDtoSource.next(serviceRequestDto);
                         },
                         error => this.errorMessage = <any>error);
}

搜索组件(点击上面的服务并订阅)如下所示 -

onSearch(value) {  
...
this.dataService.getAccountInfo(this.serviceRequestDto); //service call
this.subscription = this.dataService.serviceRequestDto$
        .subscribe( (serviceRequestDtoValue : ServiceRequestDto) => {
        // Control doesn't come here..
         this.serviceRequestDto = serviceRequestDtoValue;
         console.log('search.serviceRequestDto.length:'+this.serviceRequestDto.accountDtoList.length);
         console.log('search.serviceRequestDto.accountDtoList.name:'+this.serviceRequestDto.accountDtoList[0].name);
    });

如上所述,由于打印了 none 日志,因此控制不会出现在观察组件的订阅方法中,而且我在 console.Not 中没有收到任何错误,如果我确定m 以正确的方式使用 BehaviorSubject。

我尝试关注以下 links -

-> 未按此处所述输入订阅。
http-observables -> 当我尝试这种方式时,它确实输入订阅但随后抛出日志错误 -

cannot read property xyz of null as component logs gets printed even before i get data from service.Service logs got printed later after i got above mentioned error.

我的意图不是从点击服务的 SearchComponent 本身订阅 BehaviorSubject。我只是想测试我是否从 any component.I 中的服务中获取值,相信它与从任何其他服务订阅一样好需要 serviceRequestDto 值作为订阅语法的组件在所有组件中保持相同。

更新 1:

我尝试按照 Brandon 的建议使用 ReplaySubject(1),但在订阅组件中的主题时仍然出现以下错误。

TypeError: Cannot read property 'name' of undefined(…)

我更新的 服务 代码现在看起来像这样 -

serviceRequestDtoSource = new ReplaySubject<ServiceRequestDto>(1);
getAccountInfo(serviceRequestDto : ServiceRequestDto){
 ...
 //Logic same as earlier
 //I'm getting all values from service here in the logs I print

 }

请注意,之前我在 service 代码中使用了以下内容 -

private serviceRequestDtoSource = new BehaviorSubject<ServiceRequestDto>(null);
serviceRequestDto$ = this.serviceRequestDtoSource.asObservable();

我更新的 搜索组件 代码如下所示 -

this.dataService.getAccountInfo(this.serviceRequestDto);
this.dataService.serviceRequestDtoSource.subscribe((serviceRequestDtoValue : ServiceRequestDto) => {
this.serviceRequestDto = serviceRequestDtoValue;
console.log('search.serviceRequestDto.length:'+this.serviceRequestDto.accountDtoList.length);           
// prints 'search.serviceRequestDto.length:0'
console.log('search.serviceRequestDto.accountDtoList   name:'+this.serviceRequestDto.accountDtoList[0].name); // throws 'vendor.bundle.js:5764 ERROR TypeError: Cannot read property 'name' of undefined(…)' error
});

早期组件代码订阅主题的方式不同,虽然没有错误,但控制从未进入组件的订阅。

我的初始代码与我现在发布的不同,它基于以下 link -

我认为这取决于这样一个事实,即 BehaviorSubject 总是在订阅后立即发出它的第一个值(参见此处的大理石图 http://reactivex.io/RxJava/javadoc/rx/subjects/BehaviorSubject.html)。

现在在你的案例中发出的第一个值是 null,即你在 BehaviorSubject 的构造函数中传递的值。

解决此问题的一种方法是使用非空值检查(现在您知道可能存在合法值)或使用运算符 skip() 始终跳过第一个发出的值。

行为主体是angular中的一种observable,我们可以在订阅的方法中订阅并立即获取行为主体的值变化。因此,每当在特定行为主体的类型中声明的变量数据发生变化时,将在订阅特定行为主体的方法中通知相同的数据变化。

https://amonghorizon.blogspot.com/2020/10/behaviour-subject-with-angular.html