首页 > 解决方案 > 如何在 REST-API 端点使用 Observables 进行分页?

问题描述

我正在使用 Angular 7 并构建一个从 REST-API 端点检索数据的 web 应用程序。用户将他们的搜索字符串放入formControl可观察的公共字段中。如果输入字段中的值发生变化,则会向 API 端点发送一个 http 请求。最后,我将 http 响应作为我可以订阅的 observable 获得。但是查询结果也可以有100多个项目。然后 API 端点将 NEXT 链接发送到第二页,依此类推(API 端点分页)。

我现在的问题是,我找不到正确的方法来观察搜索输入字段并遍历从 API 端点获得的所有 NEXT 页面。分开它就像一个魅力。

有人对我的用例有好的做法吗?

我的组件文件:

export class GeomapComponent implements OnInit {
  searchTerm = new FormControl();
  constructor(private geomapService: GeomapService) { }

  ngOnInit() {
    this.searchTerm.valueChanges.pipe(
      debounceTime(400),
      distinctUntilChanged(),
      switchMap(term => this.geomapService.retrieveApi(term))
    ).subscribe(data => {
      if (data['results']) {
       ......
      }
    }
  }
}

我的服务文件:

export class GeomapService {
  retrieveUrl = new Subject<string>();

  constructor(private http: HttpClient) { }

  public retrieveApi(searchTerm: string): Observable<ApiDataResponse> {
    this.retrieveUrl.next(baseApiUrl + '?q=' + searchTerm);
    return this.retrieveUrl.pipe(
      switchMap(url => this.sendRequest(url)),
    ).subscribe(data => {
      if (data['next']) {
        this.retrieveUrl.next(data['next']);
      }
    });
  }

  public sendRequest(url: string, httpOptions = {}): Observable<ApiDataResponse> {
    return this.http.get<ApiDataResponse>(url);
  }

}

不幸的是,我收到以下错误:

TS2322:“订阅”类型不可分配给“可观察”类型。“订阅”类型中缺少属性“_isScalar”。

更新: 现在我走得更远了,因为我意识到我必须在服务中合并/合并顺序传入的 observables(由循环提供)。

  public requestApi(requestUrl: string): Observable<ApiDataResponse> {
    return this.sendRequest(requestUrl).pipe(
      mergeMap(result => {
        if (result['next']) {
          return this.requestApi(result['next']);
        } else {
          return of(result);
        }
      })
    );
  }

尽管如此,我仍然坚持使用正确的组合/转换运算符,因为在这个阶段mergeMap我订阅了最后一个响应的结果。但我也希望获得之前收到的所有回复并将其合并为一个值。

有人知道运算符中的返回应该是什么样子吗?

更新: 代码更新,删除了数组问题(ApiDataResponse[]--> ApiDataResponse

标签: angularrxjshttpclient

解决方案


所以,如果我理解得很好,你在搜索字段上有一个 observable,当你搜索时,你会调用 API 来获取结果。如果结果 > 100,那么您的 API 会发送前 100 个结果并告诉您对接下来的 100 个结果进行另一个请求,直到没有更多结果为止。

对我来说,您需要一次获得所有结果有点奇怪,不是发送 100 个第一个结果以等待用户请求 100 个下一个结果(例如,通过单击“下一页按钮“或滚动到某个限制)?

我将通过将最初的前 100 个结果存储在显示它们的组件中(可能在 BehaviourSubject 中)以及何时获取结果的下一部分(例如,当滚动位置达到一定数量或当用户单击下一个按钮),然后如果有任何结果,我会请求下一个结果...


推荐阅读