以反应方式使用分页API

时间:2019-06-20 09:50:20

标签: 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>"
    }
}

然后您可以使用GET /api/stuff?cursor=<the cursor from above>请求下一页,并且在响应中您将获得一个新的游标,因此可以继续进行直到获得一个游标为空的响应-那时最后一个可用页面。

我想要的-一堆物品

使用Reactor,我想提供一种返回类型为Flux<Item>的方法,即所有项目的流,消费者不需要知道或关心这些项目实际上是在哪一页获取的时间。

基本上,我想做一些事情,采取一种初始状态,并使用签名为State -> Mono<Tuple2<Collection<Item>, State>>(或等价物)的方法,并通过依次获取新页面直到{ {1}}表示我们已经完成。

我尝试使用Flux<Item>State来表述某些内容,但似乎它们的用例与我的用例略有不同。

我怎么到达那里?

1 个答案:

答案 0 :(得分:0)

我是反应堆新手,但是我认为expand()的用途是

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

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;
        }
    }
}