Angular 4 - rxjs BehaviorSubject usage in Service

南楼画角 提交于 2019-12-20 03:31:11

问题


My Service code looks like below -

DataService

@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);
}

Search Component (which hits above service and also subscribes) looks like below -

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);
    });

As mentioned above, control doesn't come here inside observing component's subscribe method as none of the logs are printed and also I don't get any error in console.Not sure if I'm using BehaviorSubject in proper way.

I tried to follow following links -

Angular 2 - Behavior Subject vs Observable? -> Not entering subscribe as mentioned here.
http-observables -> When I tried this way , it does enter subscribe but then throws error for logs -

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.

My intention is not to subscribe to the BehaviorSubject from SearchComponent itself which hits the service. I'm just trying to test if i get the values from service in any component.I believe it's as good as subscribing from any other component which needs serviceRequestDto values as syntax for subscribing remains same from all components.

Update 1:

I tried to use ReplaySubject(1) as suggested by Brandon, but still i was getting below error while subscribing to subject in component.

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

My updated service code looks like this now -

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

 }

Please note earlier I was using following in service code -

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

My updated Search Component code looks like this -

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
});

The way earlier component code was subscribing to subject was different and control never went inside component's subscribe though there was no error.

My initial code is different from what I've posted now and it was based on following link - delegation-eventemitter-or-observable-in-angular2


回答1:


I think this depends on the fact that BehaviorSubject emits always its first value as soon as it is subscribed (see marble diagram here http://reactivex.io/RxJava/javadoc/rx/subjects/BehaviorSubject.html).

Now the first value emitted in your case is null, i.e. The value you passed in the constructor of BehaviorSubject.

One way to overcome the problem is to use check for not null values (now that you know that there may be a legitimate one) or use the operator skip() to skip always the first emitted value.



来源:https://stackoverflow.com/questions/44574026/angular-4-rxjs-behaviorsubject-usage-in-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!