RxJava将publishsubject与timeout结合在一起

时间:2019-12-19 09:18:33

标签: android rx-java rx-java2

我希望能够订阅publishsubject并等待结果,但不能超过1分钟。

问题是,如果我这样做

publishsubject.timeout(1, TimeUnit.MINUTES).subscribe({result -> ... }, {error -> ... } )

即使在此之前我成功获得了结果,我总是会出错。如何正确实施这种方法?

2 个答案:

答案 0 :(得分:1)

在下面的示例中,我显示timeout的工作方式。对于每次发射,都会启动一个新的超时,如果在超时运行之前有新项目到达,则重新设置超时,否则将引发异常。

在示例中,我们可以在控制台上看到1、2、3的打印,并且由于超时异常而结束,因为第4个项目不在3之后的200毫秒之内。

正如我在下面的评论中所述,如果您知道何时可以终止publishSubject,则可以避免这种情况。例如,在第三项之后使用taketakeUntil或致电publishSubject.onComplete()

    @Test
    public void timeout() throws InterruptedException {
        PublishSubject<Object> publishSubject = PublishSubject.create();

        Observable<Object> timeout = publishSubject.timeout(200, TimeUnit.MILLISECONDS);

        timeout
                .subscribe(
                        e -> System.out.println(e),
                        error -> System.out.println("ERROR: " + error),
                        () -> System.out.println("complete")
                );

        sleep(50);
        publishSubject.onNext(1);
        sleep(150);
        publishSubject.onNext(2);
        sleep(199);
        publishSubject.onNext(3);
        sleep(201);
        publishSubject.onNext(4);

        Thread.sleep(2000);
    }

答案 1 :(得分:1)

您很可能会收到超时异常,因为timeout要求您的来源在指定的时间范围内持续生产商品或完成商品。因此,如果您仅向onNext发送一个PublishSubject信号,并且再也没有收到信号,则由于缺少第二个onNext呼叫,您将超时。

因此,如果您想要一项,请使用take(在timeout之前或之后):

publishsubject
   .timeout(1, TimeUnit.MINUTES)
   .take(1)
   .subscribe(result -> { /* ... */ }, error -> { /* ... */ } )