Angular 带偏移分页的异步管道
Angular async pipe with offset pagination
我有一个 observable,它从目录中拉出 12 个人并显示到带有异步管道的模板上。它命中的 API 是相当基本的,只是使用偏移分页直接传递到 SQL 查询中来抓住人们。我希望我们在第一次加载时有 API returns 前 12 个人,然后我们有一个 'load more' 按钮。希望这个按钮可以让 12 个人保持在屏幕上,但通过更改偏移量再加载 12 个,所以第一次调用是偏移量 0,接下来是偏移量 11 等
我正在查看 forkJoin 或 shareReplay 之类的东西,因为我希望它具有反应性,并且还想避免向 API 询问越来越大的响应对象 - 加载更多的示例不想要求24 就在下一个 12
所以现在 onInit 我有第一个被拉进来的人
public people$: Observable<Directory[]> = combineLatest([this.selectedLocation$,this.selectedDepartment$, this.selectedSearchQuery$]).pipe(
switchMap(([loc,dept,query]) =>
this.apiEmployeeService.getDirectory({
dept: dept?.toString(),
location: loc === 'Both' ? '%' : loc,
offset: this.offset,
limit: 12,
search: query
}),
)
所以我可以从 HTML 调用加载更多按钮来保留现有的 12 个人,然后重新启动这个可观察对象,但 offset 为 + 12
我们可以使用 BehaviorSubject
作为触发器来获取更多内容,并使用 scan
运算符将多次获取的结果累积到单个可观察对象中:
const ITEMS_PER_PAGE = 12;
export class AppComponent {
private fetch$ = new BehaviorSubject<void>(undefined);
public people$: Observable<Employee[]> = combineLatest([
this.selectedLocation$,
this.selectedDepartment$,
this.selectedSearchQuery$,
]).pipe(
switchMap(([loc, dept, search]) => this.fetch$.pipe(
switchMap((_, pageIndex) => this.apiEmployeeService.getDirectory({
dept : dept?.toString(),
location : loc === 'Both' ? '%' : loc,
offset : pageIndex * ITEMS_PER_PAGE,
limit : ITEMS_PER_PAGE,
search
})),
scan((all, page) => all.concat(page), [])
)),
);
fetchMore() {
this.fetch$.next();
}
}
嵌套 switchMap
的原因是因为我假设如果任何查询条件发生变化(location、dept、search),那么您想要offset
重置回 0。
switchMap 回调的第二个参数接收“排放指数”。我们可以用它来表示“页码”。每当 combineLatest
发出新值时,都会发生对 fetch$
的新订阅,从而有效地重置索引。
这里有一些 StackBlitz,您可以在其中看到此行为的实际效果。
我有一个 observable,它从目录中拉出 12 个人并显示到带有异步管道的模板上。它命中的 API 是相当基本的,只是使用偏移分页直接传递到 SQL 查询中来抓住人们。我希望我们在第一次加载时有 API returns 前 12 个人,然后我们有一个 'load more' 按钮。希望这个按钮可以让 12 个人保持在屏幕上,但通过更改偏移量再加载 12 个,所以第一次调用是偏移量 0,接下来是偏移量 11 等
我正在查看 forkJoin 或 shareReplay 之类的东西,因为我希望它具有反应性,并且还想避免向 API 询问越来越大的响应对象 - 加载更多的示例不想要求24 就在下一个 12
所以现在 onInit 我有第一个被拉进来的人
public people$: Observable<Directory[]> = combineLatest([this.selectedLocation$,this.selectedDepartment$, this.selectedSearchQuery$]).pipe(
switchMap(([loc,dept,query]) =>
this.apiEmployeeService.getDirectory({
dept: dept?.toString(),
location: loc === 'Both' ? '%' : loc,
offset: this.offset,
limit: 12,
search: query
}),
)
所以我可以从 HTML 调用加载更多按钮来保留现有的 12 个人,然后重新启动这个可观察对象,但 offset 为 + 12
我们可以使用 BehaviorSubject
作为触发器来获取更多内容,并使用 scan
运算符将多次获取的结果累积到单个可观察对象中:
const ITEMS_PER_PAGE = 12;
export class AppComponent {
private fetch$ = new BehaviorSubject<void>(undefined);
public people$: Observable<Employee[]> = combineLatest([
this.selectedLocation$,
this.selectedDepartment$,
this.selectedSearchQuery$,
]).pipe(
switchMap(([loc, dept, search]) => this.fetch$.pipe(
switchMap((_, pageIndex) => this.apiEmployeeService.getDirectory({
dept : dept?.toString(),
location : loc === 'Both' ? '%' : loc,
offset : pageIndex * ITEMS_PER_PAGE,
limit : ITEMS_PER_PAGE,
search
})),
scan((all, page) => all.concat(page), [])
)),
);
fetchMore() {
this.fetch$.next();
}
}
嵌套 switchMap
的原因是因为我假设如果任何查询条件发生变化(location、dept、search),那么您想要offset
重置回 0。
switchMap 回调的第二个参数接收“排放指数”。我们可以用它来表示“页码”。每当 combineLatest
发出新值时,都会发生对 fetch$
的新订阅,从而有效地重置索引。
这里有一些 StackBlitz,您可以在其中看到此行为的实际效果。