Angular onInit上的可观察订阅仅运行一次
我有一个带有名称的表和一个输入标记,当值更改时,它会过滤表的内容。 数据来自服务,并在服务上发出http请求 我有三种情况: 1-如果我只在Angular onInit上的可观察订阅仅运行一次,angular,typescript,angular2-observables,ngoninit,Angular,Typescript,Angular2 Observables,Ngoninit,我有一个带有名称的表和一个输入标记,当值更改时,它会过滤表的内容。 数据来自服务,并在服务上发出http请求 我有三种情况: 1-如果我只在ngOninit()上订阅this.ds.getDrogas(),表中会显示所有内容,但过滤器不起作用。 2-如果我仅在filterName()上订阅this.ds.getDrogas(),则表开始为空,但当我更改输入y的值时,表开始正常工作。如果我删除输入的内容,表格会显示所有的数据,如果我再次写入内容,过滤器就会工作。 3-如果我在这两个网站上都订阅了,
ngOninit()
上订阅this.ds.getDrogas()
,表中会显示所有内容,但过滤器不起作用。
2-如果我仅在filterName()
上订阅this.ds.getDrogas()
,则表开始为空,但当我更改输入y的值时,表开始正常工作。如果我删除输入的内容,表格会显示所有的数据,如果我再次写入内容,过滤器就会工作。
3-如果我在这两个网站上都订阅了,它将按预期工作。表格开始显示所有内容,当输入值更改时,过滤器工作
我知道ngOnInit()
中的代码只运行一次,但订阅不应该一直监听可观察到的更改
我提前感谢你的帮助
服务方:
getDrogas(): Observable <HttpResponses> {
return this.http.get<HttpResponses>(this.apiUrl +'/drogas')
}
Table-Component.html:
<input type="text" [(ngModel)]='contador' (ngModelChange)='filterName()'>
this.ds.getDrogas()
-返回一个可观察的。Angular不会在没有订阅的情况下从服务器请求数据。您可以在ngOnInit()中订阅它-这就是您获取初始数据的原因
我建议在ngModelChange
处理程序中使用主题为declauteTime运算符,以防止每次更改时调用API。它将如下所示:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
filterValue$ = new BehaviorSubject('');
filterValue = '';
constructor(private api: ApiSerive) {}
ngOnInit(): void {
this.filterValue$.pipe(
debounceTime(DEBOUNCE_TIME),
switchMap(filterValue => this.api.getData().pipe(
map(dataFromServer => filterData(dataFromServer, filterValue)),
)),
/* UNSUBSCRIBE HERE on compoennt destroy */
tap(filteredData => {
console.log(filteredData);
/* LOGIC OF UPDATE TABLE */
}),
).subscribe();
}
onFilterChanged(value: string): void {
console.log(value);
this.filterValue$.next(value);
}
}
function filterData(dataFromServer: any, filterValue): any {
// SOME LOGIC HERE
return dataFromServer;
}
完整代码在这里
附笔。
别忘了取消订阅组件中的可观察对象
我希望有帮助 我明白,但我不想有两个相等的订阅。如果我在服务上创建一个主题并使其发出一个值,我可以在我的组件中订阅该主题。因此,每次调用this.ds.getDrogas时,它都会通过主题发出值。这是一个好的解决方案吗?您必须订阅发出HTTP请求的Observable。我已经更新了一个答案,以显示它的外观。这是一个正确的答案,但是,我们应该考虑到共享逻辑,而不是复制粘贴,这是很简单的
filterName(){this.loadData()}
ngOnInit(){this.loadData()}
它没有复制粘贴。我已经编辑了我的答案,使之更符合最新情况。如果对您有效,请将其标记为答案。谢谢
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
filterValue$ = new BehaviorSubject('');
filterValue = '';
constructor(private api: ApiSerive) {}
ngOnInit(): void {
this.filterValue$.pipe(
debounceTime(DEBOUNCE_TIME),
switchMap(filterValue => this.api.getData().pipe(
map(dataFromServer => filterData(dataFromServer, filterValue)),
)),
/* UNSUBSCRIBE HERE on compoennt destroy */
tap(filteredData => {
console.log(filteredData);
/* LOGIC OF UPDATE TABLE */
}),
).subscribe();
}
onFilterChanged(value: string): void {
console.log(value);
this.filterValue$.next(value);
}
}
function filterData(dataFromServer: any, filterValue): any {
// SOME LOGIC HERE
return dataFromServer;
}