我的服务代码如下所示 -
的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
答案 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