以响应式方式使用分页 API

Tom*_*han 6 java pagination reactive-programming project-reactor

我试图弄清楚如何以反应式方式使用分页 API,公开项目流而不是 API 提供给我的页面。

我拥有的 - 分页 API

Slack API(以及许多其他 API)使用某种形式的元数据对象处理分页,以便在查询时/api/stuff返回一个如下所示的对象:

{
    "items": [ <list of first page you requested> ],
    "meta": {
        "cursor": "<a cursor string to get the next page>"
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用 请求下一页GET /api/stuff?cursor=<the cursor from above>,在响应中您将获得一个新的光标,因此您可以继续下去,直到收到光标为空的响应 - 这就是最后一个可用页面。

我想要什么 - 一系列物品

对于 Reactor,我想提供一种具有返回类型的方法Flux<Item>,即所有项目的流,其中消费者不需要知道或关心这些项目实际上一次一页地获取。

基本上,我想做一些事情,它需要一个初始状态和一个带有签名State -> Mono<Tuple2<Collection<Item>, State>>(或等效)的方法,并Flux<Item>通过顺序获取新页面来给我一个,直到State指示我们完成为止。

我尝试使用Flux.createor来制定某些内容Flux.generate,但它们的用例似乎与我的略有不同。

我如何到达那里?

JB *_*zet 3

我是一个反应堆新手,但我认为这就是Expand()的用途:

这是一个完整的演示,其中getFirstPage()模拟getNextPage()了 slack API。getNextPage()当光标到达值 5 时返回最后一页。

public class Slack {
    public static void main(String[] args) {
        getFirstPage().expand(page -> getNextPage(page))
                      .flatMapIterable(page -> page.getResult())
                      .subscribe(System.out::println);
    }

    private static Mono<Page> getFirstPage() {
        System.out.println("getting first page");
        return Mono.just(new Page(Arrays.asList("page0-1", "page0-2"), 1));
    }

    private static Mono<Page> getNextPage(Page page) {
        System.out.println("getting page " + page.getCursor());
        if (page.getCursor() == null) {
            return Mono.empty();
        }
        Integer nextCursor = (page.getCursor() == 5) ? null : page.getCursor() + 1;
        return Mono.just(new Page(Arrays.asList("page" + page.getCursor() + "-1", "page" + page.getCursor() + "-2"), nextCursor));
    }

    static class Page {
        private List<String> result;
        private Integer cursor;

        public Page(List<String> result, Integer cursor) {
            this.result = result;
            this.cursor = cursor;
        }

        public List<String> getResult() {
            return result;
        }

        public Integer getCursor() {
            return cursor;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)