简体   繁体   中英

RXJava - emit “clock tick” item since last item received

I have an Observable emitting items, and I would like to merge into it special items acting as "time ticks" since the last item has been received.

I was trying to play around with timeout + onErrorXXX or interval s, but could not get it to work as expected.

import io.reactivex.Observable;
import io.reactivex.functions.Function;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class RXTest {
    private static final Logger log = Logger.getLogger(RXTest.class);

    @Test
    public void rxTest() throws InterruptedException {
        log.info("Starting");

        Observable.range(0, 26)
                .concatMap(
                        item -> Observable.just(item)
                                .delay(item, TimeUnit.SECONDS)
                )
                .timeout(100, TimeUnit.MILLISECONDS)
//                .retry()
                .onErrorResumeNext((Function) throwable -> {
                    if (throwable instanceof TimeoutException) {
                        return Observable.just(-1);
                    }
                    throw new RuntimeException((Throwable)throwable);
                })
                .subscribe(
                        item -> log.info("Received " + item),
                        throwable -> log.error("Thrown" + throwable),
                        () -> log.info("Completed")
                );

        Thread.sleep(30000);
    }
}

I would expect it to output something like:

00:00.000 Received 0
00:00.100 Received -1
00:00.200 Received -1
... (more Received -1 every 100 millis)
00:01.000 Received 1
00:01.100 Received -1
00:01.200 Received -1
...
00:03.000 Received 2
00:03.100 Received -1
00:03.200 Received -1
...

But instead, it receives -1 only once and then completes.

EDIT
Hopefully this marbles diagram would make it easier to understand: 在此处输入图片说明

I don't clearly understand what you want, but the expected output will be if you change onResumeNext() to return

Observable.interval(100, TimeUnit.MILLISECONDS)
  .take(2)
  .map(__ -> -1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM