多次发出 RxJS http 请求
RxJS http request made multiple times
我已将 open()
方法附加到我的 ng-select 元素,以便用来自外部 API.
的数据填充它
我遇到的问题:如果我打开下拉菜单 5 次然后输入一个字母,它将向服务器发出 5 个 http 请求以便用数据填充它。当我使用虚拟滚动功能时出现同样的问题。
component.html
<ng-select [items]="filterValuesBuffer"
[typeahead]="filterValuesInput$[filter.name]"
[virtualScroll]="true"
[multiple]="true"
[closeOnSelect]="false"
[loading]="filterValuesLoading[filter.name]"
[(ngModel)]="filter.filter_values"
(scrollToEnd)="onScrollToEnd(filter.name)"
(open)="onFilterOpen(filter.name)"
typeToSearchText="No values found"
bindLabel="name">
</ng-select>
component.ts
filterValuesInput$: Map<string, Subject<string>[]> = new Map();
onFilterOpen(filterName) {
this.filterValuesLoading[filterName] = true;
this.getFilterValues(filterName, '')
.subscribe(res => {
this.afterKey = res.after_key;
this.filterValuesLoading[filterName] = false;
this.filterValuesBuffer = res.filter_values;
});
}
getFilterValues(filterName, afterKey) {
return this.filterValuesInput$[filterName].pipe(
tap(() => this.filterValuesLoading[filterName] = true),
startWith(''),
distinctUntilChanged(),
switchMap(term => this.search.getFilterValues(filterName, '' + term, '' + afterKey)),
)
}
如何防止这种行为?
编辑虚拟卷轴:
(scrollToEnd)="fetchMore(filter.name)"
fetchMore(filterName) {
this.filterValuesLoading[filterName] = true;
this.getFilterValues(filterName, this.afterKey)
.subscribe(res => {
this.afterKey = res.after_key;
this.filterValuesLoading[filterName] = false;
this.filterValuesBuffer = this.filterValuesBuffer.concat(res.filter_values);
})
}
那是因为您从未取消订阅 getFilterValues()
。您可能应该绑定到 (close)
并在那里取消订阅:
onFilterOpen(filterName) {
this.subscription = this.getFilterValues(filterName, '')
.subscribe(res => ...);
}
onFilterClose() {
this.subscription.unsubscribe();
}
您最终可以使用 takeWhile()
运算符。参见
尝试像下面这样改变你的方法:-
public openedFiterName = {};
onFilterOpen(filterName) {
this.filterValuesLoading[filterName] = true;
if(this.openedFilterName[filterName]) {
this.filterValuesLoading[filterName] = false;
this.filterValuesBuffer = this.openedFilterName[filterName];
return;
}
this.getFilterValues(filterName, '')
.subscribe(res => {
this.openedFiterName[filterName] = res.filter_values;
this.afterKey = res.after_key;
this.filterValuesLoading[filterName] = false;
this.filterValuesBuffer = res.filter_values;
});
}
fetchMore(filterName) {
this.filterValuesLoading[filterName] = true;
this.getFilterValues(filterName, this.afterKey)
.pipe(take(1)).subscribe(res => {
this.afterKey = res.after_key;
this.filterValuesLoading[filterName] = false;
this.filterValuesBuffer = this.filterValuesBuffer.concat(res.filter_values);
})
}
我已将 open()
方法附加到我的 ng-select 元素,以便用来自外部 API.
我遇到的问题:如果我打开下拉菜单 5 次然后输入一个字母,它将向服务器发出 5 个 http 请求以便用数据填充它。当我使用虚拟滚动功能时出现同样的问题。
component.html
<ng-select [items]="filterValuesBuffer"
[typeahead]="filterValuesInput$[filter.name]"
[virtualScroll]="true"
[multiple]="true"
[closeOnSelect]="false"
[loading]="filterValuesLoading[filter.name]"
[(ngModel)]="filter.filter_values"
(scrollToEnd)="onScrollToEnd(filter.name)"
(open)="onFilterOpen(filter.name)"
typeToSearchText="No values found"
bindLabel="name">
</ng-select>
component.ts
filterValuesInput$: Map<string, Subject<string>[]> = new Map();
onFilterOpen(filterName) {
this.filterValuesLoading[filterName] = true;
this.getFilterValues(filterName, '')
.subscribe(res => {
this.afterKey = res.after_key;
this.filterValuesLoading[filterName] = false;
this.filterValuesBuffer = res.filter_values;
});
}
getFilterValues(filterName, afterKey) {
return this.filterValuesInput$[filterName].pipe(
tap(() => this.filterValuesLoading[filterName] = true),
startWith(''),
distinctUntilChanged(),
switchMap(term => this.search.getFilterValues(filterName, '' + term, '' + afterKey)),
)
}
如何防止这种行为?
编辑虚拟卷轴:
(scrollToEnd)="fetchMore(filter.name)"
fetchMore(filterName) {
this.filterValuesLoading[filterName] = true;
this.getFilterValues(filterName, this.afterKey)
.subscribe(res => {
this.afterKey = res.after_key;
this.filterValuesLoading[filterName] = false;
this.filterValuesBuffer = this.filterValuesBuffer.concat(res.filter_values);
})
}
那是因为您从未取消订阅 getFilterValues()
。您可能应该绑定到 (close)
并在那里取消订阅:
onFilterOpen(filterName) {
this.subscription = this.getFilterValues(filterName, '')
.subscribe(res => ...);
}
onFilterClose() {
this.subscription.unsubscribe();
}
您最终可以使用 takeWhile()
运算符。参见
尝试像下面这样改变你的方法:-
public openedFiterName = {};
onFilterOpen(filterName) {
this.filterValuesLoading[filterName] = true;
if(this.openedFilterName[filterName]) {
this.filterValuesLoading[filterName] = false;
this.filterValuesBuffer = this.openedFilterName[filterName];
return;
}
this.getFilterValues(filterName, '')
.subscribe(res => {
this.openedFiterName[filterName] = res.filter_values;
this.afterKey = res.after_key;
this.filterValuesLoading[filterName] = false;
this.filterValuesBuffer = res.filter_values;
});
}
fetchMore(filterName) {
this.filterValuesLoading[filterName] = true;
this.getFilterValues(filterName, this.afterKey)
.pipe(take(1)).subscribe(res => {
this.afterKey = res.after_key;
this.filterValuesLoading[filterName] = false;
this.filterValuesBuffer = this.filterValuesBuffer.concat(res.filter_values);
})
}