Angular 4 - 服务中的rxjs BehaviorSubject用法

时间:2017-06-15 18:00:00

标签: angular rxjs behaviorsubject

我的服务代码如下所示 -

的DataService

<div class="test"></div>

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

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

如上所述,控件并没有来到观察组件的订阅方法,因为没有打印任何日志,我也没有在控制台中收到任何错误。不确定我是否#&# 39; m以正确的方式使用BehaviorSubject。

我尝试按照以下链接 -

Angular 2 - Behavior Subject vs Observable? - &gt;不按此处提及订阅。
http-observables - &gt;当我尝试这种方式时,它会输入subscribe但是然后抛出日志错误 -

  

无法读取属性xyz of null   因为组件日志甚至在我从服务中获取数据之前就被打印了。服务日志在我得到上述错误之后被打印出来。

我的目的不是订阅SearchComponent本身的BehaviorSubject,它会命中服务。我只是想测试一下我是否从 任何 组件中获取服务中的值。我相信它与订阅任何其他组件一样好需要 serviceRequestDto 值,因为订阅的语法与所有组件保持相同。

更新1:

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

  

TypeError:无法读取属性&#39; name&#39;未定义的(...)

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

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

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

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

 }

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

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

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

我的初始代码与我现在发布的代码不同,它基于以下链接 - delegation-eventemitter-or-observable-in-angular2

2 个答案:

答案 0 :(得分:5)

我认为这取决于BehaviorSubject一旦订阅就会一直发出它的第一个值(参见这里的大理石图http://reactivex.io/RxJava/javadoc/rx/subjects/BehaviorSubject.html)。

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

解决此问题的一种方法是使用check not not null值(现在您知道可能存在合法值)或使用operator skip()始终跳过第一个发射值。

答案 1 :(得分:0)

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

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