为什么rx-java邮政编码失败

时间:2016-12-10 01:59:47

标签: java rx-java2

这是测试代码

    final Flowable<Integer> f1 = Flowable.fromPublisher(s -> {
        s.onNext(Integer.valueOf(1));
        s.onComplete();
    });


    final Flowable<Integer> f2 = Flowable.fromPublisher(s -> {
        s.onNext(Integer.valueOf(2));
        s.onComplete();
    });

    Flowable.zip(f1, f2, (i1, i2) -> "" + i1 + i2)
            .blockingSubscribe(System.out::println);

它会得到

Exception in thread "main" java.lang.NullPointerException
    at io.reactivex.internal.operators.flowable.FlowableZip$ZipSubscriber.onNext(FlowableZip.java:386)

我不明白为什么?

如果我像这样更新代码

    final Flowable<Integer> f1 = Flowable.<Integer>fromPublisher(s -> {
        s.onNext(Integer.valueOf(1));
        s.onComplete();
    }).onErrorResumeNext(Flowable.empty());


    final Flowable<Integer> f2 = Flowable.<Integer>fromPublisher(s -> {
        s.onNext(Integer.valueOf(2));
        s.onComplete();
    }).onErrorResumeNext(Flowable.empty());

    Flowable.zip(f1, f2, (i1, i2) -> "" + i1 + i2)
            .blockingSubscribe(System.out::println);

它将按预期打印12。但为什么?它没有意义。

1 个答案:

答案 0 :(得分:1)

问题是,您使用Publisher<T>违反了fromPublisher的合同。

发布商需要按照Reactive Streams合同中指定的非常具体的方式行事。这种行为包括在进行任何其他呼叫之前呼叫Subscriber.onSubscribe()并尊重该用户的背压。

由于您没有致电onSubscribe,因此内部queue变量永远不会被初始化,而queue.offer方法中对onNext的调用会导致NPE。

据推测,通过使用onErrorResumeNext,实施可以确保所有内容都得到正确调用,并且可以确保&#39;无效的状态。

要解决您的问题,有两种可能:

  1. 请勿使用Flowable.fromPublisher。它旨在与Reactive Streams宣言的其他实现相桥接,并且没有任何安全措施。而是使用正确处理初始化和背压的Flowable.create
  2. 使用非背压识别Observable,因为您的用例似乎不关心背压。再次使用Observable.create方法安全使用。