私のサービスコードは以下のようになります -
データサービス
@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);
});
上記のように、ログが出力されず、コンソールにエラーが表示されないため、監視コンポーネントのサブスクライブ メソッド内に制御が入りません。適切な方法で BehaviorSubject を使用しているかどうかはわかりません。
次のリンクをたどってみました -
Angular 2 - 行動主体と観察対象? →こちらに記載のサブスクライブには入っていません。
http-observables -> この方法を試してみると、サブスクライブに入りますが、ログのエラーがスローされます -
サービスからデータを取得する前でもコンポーネント ログが印刷されるため、null のプロパティ xyz を読み取れません 。上記のエラーが発生した後、サービス ログが後で印刷されます。
私の意図は、サービスにヒットする SearchComponent 自体から BehaviorSubject にサブスクライブすることではありません。コンポーネントのサービスから値を取得するかどうかをテストしようとしています。サブスクライブの構文はすべてのコンポーネントで同じであるため、 serviceRequestDto値を必要とする他のコンポーネントからサブスクライブするのと同じくらい良いと思います。
更新 1:
ブランドンの提案に従って ReplaySubject(1) を使用しようとしましたが、コンポーネントでサブジェクトをサブスクライブしているときにエラーが発生しました。
TypeError: undefined(…) のプロパティ '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();
更新された検索コンポーネントのコードは次のようになります -
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
});
以前のコンポーネント コードがサブジェクトにサブスクライブしていた方法は異なり、エラーはありませんでしたが、コントロールがコンポーネントのサブスクライブ内に入ることはありませんでした。
私の最初のコードは、現在投稿したものとは異なり、次のリンクに基づいていました- delegation-eventemitter-or-observable-in-angular2