Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 请求反应堆中的下一个';只有在需要的时候,它才会流动_Java_Spring_Spring Webflux_Project Reactor - Fatal编程技术网

Java 请求反应堆中的下一个';只有在需要的时候,它才会流动

Java 请求反应堆中的下一个';只有在需要的时候,它才会流动,java,spring,spring-webflux,project-reactor,Java,Spring,Spring Webflux,Project Reactor,我有一个API,它返回一个限制为100个实体的实体列表。如果有更多实体,它将返回下一页的令牌 我想创建一个通量,它返回(所有页面的)所有实体,但仅在需要时(如果请求的话)返回 我写了这段代码: class Page { String token; List<Object> entities; } Flux<Object> load(String token, final Function<String, Mono<Page>> f

我有一个API,它返回一个限制为100个实体的实体列表。如果有更多实体,它将返回下一页的令牌

我想创建一个通量,它返回(所有页面的)所有实体,但仅在需要时(如果请求的话)返回

我写了这段代码:

class Page {
    String token;
    List<Object> entities;
}

Flux<Object> load(String token, final Function<String, Mono<Page>> fct) {
    return fct.apply(token).flatMapMany(page -> {
        if (page.token == null) {
            // no more pages
            return Flux.fromIterable(page.entities);
        }

        return Flux.fromIterable(page.entities).concatWith(Flux.defer(() -> load(page.token, fct)));
    });
}
预期为:在最后一个请求(1)之后加载第2页


这几乎像是在某个地方有预取,但我看不到在哪里。有什么想法吗?

好的,我找到了。没有预先回迁。实际上是
Flux.defer
在订阅时加载下一页,而不是在请求时加载

一个快速(且不干净)的测试修复了以下问题:

Flux<Object> load(String token, final Function<String, Mono<Page>> fct) {
    return fct.apply(token).flatMapMany(page -> {
        if (page.token == null) {
            // no more pages
            return Flux.fromIterable(page.entities);
        }

        return Flux
                .fromIterable(page.entities)
                .concatWith(
                        // Flux.defer(() -> load(page.token, fct))
                        Flux.create(s -> {
                            DelegateSubscriber[] ref = new DelegateSubscriber[1];

                            s.onRequest(l -> {
                                if (ref[0] == null) {
                                    ref[0] = new DelegateSubscriber(s);
                                    load(page.token, fct).subscribe(ref[0]);
                                }
                                ref[0].request(l);
                            });
                        }));
    });
}

static class DelegateSubscriber extends BaseSubscriber<Object> {

    FluxSink<Object> delegate;

    public DelegateSubscriber(final FluxSink<Object> delegate) {
        this.delegate = delegate;
    }

    @Override
    protected void hookOnSubscribe(Subscription subscription) {
        // nothing
    }

    @Override
    protected void hookOnNext(Object value) {
        delegate.next(value);
    }

    @Override
    protected void hookOnError(Throwable throwable) {
        delegate.error(throwable);
    }
}
通量加载(字符串标记,最终函数fct){ 返回fct.apply(令牌).flatMapMany(第->{ 如果(page.token==null){ //没有更多的页面 返回通量.fromIterable(第页实体); } 回流通量 .fromIterable(第页实体) 康卡特维思先生( //流量延迟(()->加载(page.token,fct)) 通量。创建(s->{ DelegateSubscriber[]ref=新的DelegateSubscriber[1]; s、 onRequest(l->{ if(ref[0]==null){ ref[0]=新的被委派订户; 加载(page.token,fct).订阅(ref[0]); } 参考[0]。请求(l); }); })); }); } 静态类DelegateSubscriber扩展BaseSubscriber{ FluxSink代表; 公共委托订户(最终FluxSink委托){ this.delegate=委托; } @凌驾 受保护的void hookonsubscripte(订阅){ //没什么 } @凌驾 受保护的void hookOnNext(对象值){ 下一步(值); } @凌驾 受保护的空挂钩器(可丢弃){ 委托错误(可丢弃); } }
您可以执行以下操作:从适配器创建一个流量,该流量将在内部订阅第一页和缓冲区元素。当不需要发出更多元素且存在下一页时,适配器将创建对下一页的新订阅
Flux<Object> load(String token, final Function<String, Mono<Page>> fct) {
    return fct.apply(token).flatMapMany(page -> {
        if (page.token == null) {
            // no more pages
            return Flux.fromIterable(page.entities);
        }

        return Flux
                .fromIterable(page.entities)
                .concatWith(
                        // Flux.defer(() -> load(page.token, fct))
                        Flux.create(s -> {
                            DelegateSubscriber[] ref = new DelegateSubscriber[1];

                            s.onRequest(l -> {
                                if (ref[0] == null) {
                                    ref[0] = new DelegateSubscriber(s);
                                    load(page.token, fct).subscribe(ref[0]);
                                }
                                ref[0].request(l);
                            });
                        }));
    });
}

static class DelegateSubscriber extends BaseSubscriber<Object> {

    FluxSink<Object> delegate;

    public DelegateSubscriber(final FluxSink<Object> delegate) {
        this.delegate = delegate;
    }

    @Override
    protected void hookOnSubscribe(Subscription subscription) {
        // nothing
    }

    @Override
    protected void hookOnNext(Object value) {
        delegate.next(value);
    }

    @Override
    protected void hookOnError(Throwable throwable) {
        delegate.error(throwable);
    }
}