使用 switchMap 取消订阅以前的 http 请求,只接收最新的请求
using switchMap to unsubscribe previous http request and only take latest one
我目前面临一个问题,第一次搜索可能需要 5 秒,第二次需要 2 秒,问题是,第一次搜索需要更长的时间,"erase"之后完成的请求,因为调用在之后结束。
我试着阅读
switchMap
在 rxJs 中并尝试使用它,但是 根据我的尝试,它不会取消订阅之前的请求并删除结果。
我这里可能做错了什么,但我不能准确指出问题所在。
Merge 在结果中有 3 个变化来源(分页、排序或新搜索条件),以及对 sendSearchCriteria returns 使用的数据的调用。
sendSearchCriteria returns 一个 Observable
你有没有想到我做错了什么?
感谢您的帮助,
private loadDogsResults = (filtersInformation: FilterSearchCriteria) => {
merge(this.sort.sortChange, this.paginator.page, of(filtersInformation))
.pipe(
distinctUntilChanged(),
tap(() => (this.isLoading = true)),
switchMap(() => this.sendSearchCriteria(filtersInformation)),
//mergeMap(() => this.sendSearchCriteria(filtersInformation)),
map(data => this.formatResults(data)),
finalize(() => (this.isLoading = false)),
catchError(error => this.handleError(error)),
takeUntil(this._onDestroy$)
)
.subscribe((result: any[]) => {
if (result.length > 0) {
this.setDisplayedColumns(result[0]);
}
this.isLoading = false;
});
}
哪个事件触发了 search
?此事件应该是您的 Observable
的来源,即 "piped" 和 switchMap
运算符。
正如我在这里看到的,如果您为每个事件调用 loadDogsResults()
,它将不起作用,因为您每次都创建一个新的 Observable
。 of(filtersInformation)
是一个 Observable,它在订阅 observable 时发出一次 filtersInformation
值,我认为这不是预期的行为。
您正在对 3 个单独的可观察对象进行合并,这将导致您在 3 个不同的场合进入管道,并触发 3 个单独的 sendSearchCriteria 调用。如果你想做的是调用 sortChange 和 page,得到两者的结果然后调用 sendSearchCriteria,你可以...
private loadDogsResults = (filtersInformation: FilterSearchCriteria) => {
forkJoin(this.sort.sortChange, this.paginator.page)
.pipe(
distinctUntilChanged(),
tap(() => (this.isLoading = true)),
switchMap(() => this.sendSearchCriteria(filtersInformation)),
//mergeMap(() => this.sendSearchCriteria(filtersInformation)),
map(data => this.formatResults(data)),
finalize(() => (this.isLoading = false)),
catchError(error => this.handleError(error)),
takeUntil(this._onDestroy$)
)
.subscribe((result: any[]) => {
if (result.length > 0) {
this.setDisplayedColumns(result[0]);
}
this.isLoading = false;
});
}
但是请记住,在您的订阅中,您将只能访问来自 sendSearchCriteria 的响应。
一位同事帮助我找到了问题 :) 我们尝试了 forkJoin、combineLatest 和多个选项,但最大的问题是 initialization/subscription 以一种奇怪的方式完成。
我们现在创建了一个 searchTriggerSubject 并添加了这些行
private initializeSubscription() {
this.searchTriggerSubscription = this.searchTriggerSubject.pipe(
tap(() => (this.isLoading = true)),
switchMap(() => this.sendSearchCriteria(this.claimsFilters)),
map(data => this.formatResults(data)),
catchError(error => this.handleError(error)),
takeUntil(this._onDestroy$)
).subscribe((result: any[]) => {
if (result.length > 0) {
this.setDisplayedColumns(result[0]);
}
this.isLoading = false;
});
}
private initializeSearchTriggerValues() {
this.sort.sortChange.subscribe(() => this.searchTriggerSubject.next())
this.paginator.page.subscribe(() => this.searchTriggerSubject.next())
this.filtersSubscription = this.claimsFiltersService.getFilterValues()
.pipe(
filter(filters => filters !== null),
tap((filter) => this.claimsFilters = filter)
)
.subscribe(() => this.searchTriggerSubject.next());
}
过滤器来自服务,所以我们这样做是为了避免这个问题。
需要进行一些重构
非常感谢大家提供不同的线索,有多个主题会更容易
我目前面临一个问题,第一次搜索可能需要 5 秒,第二次需要 2 秒,问题是,第一次搜索需要更长的时间,"erase"之后完成的请求,因为调用在之后结束。
我试着阅读
switchMap
在 rxJs 中并尝试使用它,但是 根据我的尝试,它不会取消订阅之前的请求并删除结果。
我这里可能做错了什么,但我不能准确指出问题所在。
Merge 在结果中有 3 个变化来源(分页、排序或新搜索条件),以及对 sendSearchCriteria returns 使用的数据的调用。
sendSearchCriteria returns 一个 Observable
你有没有想到我做错了什么?
感谢您的帮助,
private loadDogsResults = (filtersInformation: FilterSearchCriteria) => {
merge(this.sort.sortChange, this.paginator.page, of(filtersInformation))
.pipe(
distinctUntilChanged(),
tap(() => (this.isLoading = true)),
switchMap(() => this.sendSearchCriteria(filtersInformation)),
//mergeMap(() => this.sendSearchCriteria(filtersInformation)),
map(data => this.formatResults(data)),
finalize(() => (this.isLoading = false)),
catchError(error => this.handleError(error)),
takeUntil(this._onDestroy$)
)
.subscribe((result: any[]) => {
if (result.length > 0) {
this.setDisplayedColumns(result[0]);
}
this.isLoading = false;
});
}
哪个事件触发了 search
?此事件应该是您的 Observable
的来源,即 "piped" 和 switchMap
运算符。
正如我在这里看到的,如果您为每个事件调用 loadDogsResults()
,它将不起作用,因为您每次都创建一个新的 Observable
。 of(filtersInformation)
是一个 Observable,它在订阅 observable 时发出一次 filtersInformation
值,我认为这不是预期的行为。
您正在对 3 个单独的可观察对象进行合并,这将导致您在 3 个不同的场合进入管道,并触发 3 个单独的 sendSearchCriteria 调用。如果你想做的是调用 sortChange 和 page,得到两者的结果然后调用 sendSearchCriteria,你可以...
private loadDogsResults = (filtersInformation: FilterSearchCriteria) => {
forkJoin(this.sort.sortChange, this.paginator.page)
.pipe(
distinctUntilChanged(),
tap(() => (this.isLoading = true)),
switchMap(() => this.sendSearchCriteria(filtersInformation)),
//mergeMap(() => this.sendSearchCriteria(filtersInformation)),
map(data => this.formatResults(data)),
finalize(() => (this.isLoading = false)),
catchError(error => this.handleError(error)),
takeUntil(this._onDestroy$)
)
.subscribe((result: any[]) => {
if (result.length > 0) {
this.setDisplayedColumns(result[0]);
}
this.isLoading = false;
});
}
但是请记住,在您的订阅中,您将只能访问来自 sendSearchCriteria 的响应。
一位同事帮助我找到了问题 :) 我们尝试了 forkJoin、combineLatest 和多个选项,但最大的问题是 initialization/subscription 以一种奇怪的方式完成。
我们现在创建了一个 searchTriggerSubject 并添加了这些行
private initializeSubscription() {
this.searchTriggerSubscription = this.searchTriggerSubject.pipe(
tap(() => (this.isLoading = true)),
switchMap(() => this.sendSearchCriteria(this.claimsFilters)),
map(data => this.formatResults(data)),
catchError(error => this.handleError(error)),
takeUntil(this._onDestroy$)
).subscribe((result: any[]) => {
if (result.length > 0) {
this.setDisplayedColumns(result[0]);
}
this.isLoading = false;
});
}
private initializeSearchTriggerValues() {
this.sort.sortChange.subscribe(() => this.searchTriggerSubject.next())
this.paginator.page.subscribe(() => this.searchTriggerSubject.next())
this.filtersSubscription = this.claimsFiltersService.getFilterValues()
.pipe(
filter(filters => filters !== null),
tap((filter) => this.claimsFilters = filter)
)
.subscribe(() => this.searchTriggerSubject.next());
}
过滤器来自服务,所以我们这样做是为了避免这个问题。
需要进行一些重构
非常感谢大家提供不同的线索,有多个主题会更容易