2017-06-15 80 views
2
使用

我的服務代碼看起來像下面 -角4 - rxjs BehaviorSubject在服務

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

搜索組件(其中命中上述服務,也可以訂閱)看起來像下面 -

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 - Behavior Subject vs Observable? - >不進入訂閱這裏提到。
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。我只是想測試,如果我得到從服務中值的任何 component.I相信它是來自哪個需要serviceRequestDto值語法訂閱任何其他組件訂閱好保持所有的組件相同。

更新1:

我試圖用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 

} 

請早注意我用的是在服務以下代碼 -

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

回答

5

我認爲這取決於BehaviorSubject只要它訂閱(總是發出了超值的事實在這裏看到大理石圖http://reactivex.io/RxJava/javadoc/rx/subjects/BehaviorSubject.html)。

現在,您的案例中發出的第一個值爲空,即您在BehaviorSubject的構造函數中傳遞的值。

解決此問題的一種方法是使用檢查非空值(現在您知道可能有合法的值)或使用運算符skip()跳過總是第一個發出的值。

+4

使用'ReplaySubject(1)'而不是'BehaviorSubject(null)'來避免獲得第一個空值。 – Brandon