我有一个组件,上面有2个子组件,父组件从URL获取参数进行一些计算并在模板上显示一些数据。
但是我还使用URL参数通过子组件上的@Input()传递给2个子组件。
我正在尝试寻找一个问题的解决方案,该问题可以在用户将所有数据加载到子组件之前查看用户是否导航。
因此,当用户导航到父组件时,我获得了其在URL上传递的ID,并调用API向用户显示一些数据。同时,我将该ID传递给调用另一个API并提取更多数据的子组件。
问题在于,用户可以在父组件显示上单击链接并更改URL上的ID,这将根据URL ID加载新数据,然后将其再次传递给子组件,这将导致它可以从API中提取新数据集。如果在所有数据从API调用返回之前单击快速,您会注意到子组件上的第一个API调用仍在进行,而第二个调用已启动。
所以发生的是,您将看到显示的第一个API数据,并且在第二次调用完成之后,数据将在子组件上使用新数据集进行更新。
防止这种情况发生的最佳方法是什么?我应该在子API调用中添加延迟吗?
答案 0 :(得分:1)
听起来您已经让父母通过更改ID来更新孩子。
如果让孩子将其@Input
视为Observable
,那么如果传入ID在HTTP请求之前发生更改,则可以利用switchMap
自动取消挂起的HTTP请求完成。
您可以通过以下方式实现此目标:
Subject
实例来保存ID,ngOnChanges
使Subject
的ID更改保持更新,Subject
传递Observable
(作为switchMap
)以获取HTTP请求Observable
,并且Observable
,对响应执行任何工作。以下(未经测试的)代码应接近您的需求:
private id: Subject = new BehaviorSubject(null);
private data: Observable;
private sub: Subscription;
ngOnChanges(changes: SimpleChanges) {
if (changes['id']) {
this.id.next(changes['id']);
}
}
ngOnInit() {
this.data = this.id.asObservable().pipe(
filter(id => id !== null),
switchMap(id => GET_RESPONSE_OBSERVABLE_FOR(id)),
map(response => {
// build & return data structure suitable for template
})
);
this.sub = this.data.subscribe(data => {
// update child according to data
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
如果您可以使用async
管道订阅模板中的可观察对象,那么您甚至不需要在ngOnDestroy
时手动退订。
这种方法消除了对任何硬编码延迟的需求。
答案 1 :(得分:0)
答案 2 :(得分:0)
在这种情况下,您可以做什么。将子项输入为Observable
。
父级完成数据加载后,向子级发出{id}。
父组件
@Input() ID: string;
public id$: Observable<string>;
ngOnInit(){
this.httpService.get('urltofetchdatawith{ID}')
.subscribe(data =>{
if(data){
// After fetching the data in parent emit the {id} to child
this.id$ = new Observable<string>(ob => ob.next(this.ID));
}
})
}
父组件模板
<child-component [id]="id$"> </child-component>
子组件
@Input() id: Observable<string>;
ngOnChanges(){
if(id){
this.id
.pipe(
map(value => value),
switchMap(value => this.httpService('urltofetchdata{value}'))
)
.subscribe(data =>{
// Child data
})
}
}