javascript - 如何正确地将 HttpClient 请求的结果多播到 Angular 中的多个组件?
问题描述
我正在尝试HttpClient
post
在我的 Angular 应用程序中发送请求多个组件的结果。每当成功执行新请求时,我都会使用Subject
并调用它的方法。每个组件订阅服务的.next()
post
Subject
故障服务定义为
@Injectable()
export class BuildingDataService {
public response: Subject<object> = new Subject<object>();
constructor (private http: HttpClient) { }
fetchBuildingData(location) {
...
this.http.post(url, location, httpOptions).subscribe(resp => {
this.response.next(resp);
});
}
订阅的组件BuildingService.response
如下
@Component({
template: "<h1>{{buildingName}}</h1>"
...
})
export class SidepanelComponent implements OnInit {
buildingName: string;
constructor(private buildingDataService: BuildingDataService) { }
ngOnInit() {
this.buildingDataService.response.subscribe(resp => {
this.buildingName = resp['buildingName'];
});
}
updateBuildingInfo(location) {
this.buildingDataService.fetchBuildingData(location);
}
}
updateBuildingInfo
由用户点击地图触发。
从服务器检索数据并将其传递给组件是可行的:我可以将有效负载输出到每个组件的控制台。但是,组件的模板无法更新。
在今天大部分时间谷歌搜索和摆弄之后,我发现这个实现不会触发 Angular 的更改检测。解决方法是
- 将我的呼叫包含
next()
在服务中NgZone.run(() => { this.response.next(resp); }
- 在组件中调用
ApplicationRef.tick()
后this.title = resp['title']
。
对于这样一个微不足道的用例,这两种解决方案都感觉像是肮脏的黑客攻击。必须有更好的方法来实现这一点。
因此,我的问题是:一次获取数据并将其发送到多个组件的正确方法是什么?
我还想了解为什么我的实现会避开 Angular 的变更检测系统。
编辑原来我是HttpClient
在 Angular 区域之外发起呼叫,因此它无法检测到我的更改,有关更多详细信息,请参阅我的答案。
解决方案
一种方法是使用管道获取并在模板Observable
中Subject
使用它:async
(building | async)?.buildingName
此外,如果不同的组件在不同的时间订阅服务,您可能必须BehaviorSubject
使用Subject
.
@Injectable()
export class BuildingDataService {
private responseSource = new Subject<object>();
public response = this.responseSource.asObservable()
constructor (private http: HttpClient) { }
fetchBuildingData(location) {
this.http.post(url, location, httpOptions).subscribe(resp => {
this.responseSource.next(resp);
});
}
}
@Component({
template: "<h1>{{(building | async)?.buildingName}}</h1>"
...
})
export class SidepanelComponent implements OnInit {
building: Observable<any>;
constructor(private buildingDataService: DataService) {
this.building = this.buildingDataService.response;
}
ngOnInit() {
}
updateBuildingInfo(location) {
this.buildingDataService.fetchBuildingData(location);
}
}
推荐阅读
- r - Geom_rect 从 x 轴 R 的最终值开始
- node.js - 使用节点 10 进行 HTTPS 请求时接收“EPROTO”
- c - 如何在 C 中将数组声明为匿名结构成员(或解决方法)?
- c++ - 显式传递模板参数时,函数模板参数丢失常量?
- c++ - 如何在 Ubuntu 20.04 上安装 libstdc++6 调试符号?
- javascript - 我应该如何在 AllValidate 函数中包含这些函数?
- python - 如何创建包含 sqlite 数据库的 python exe 文件?
- android - Android WebView 和 webrtc hello world 示例
- angular - 如何在 TypeScript 中正确键入 RXJS WebSocket?
- javascript - 如何通过单击按钮的数据触发 setState 函数以从子组件到父组件做出反应