如何在RxJava中创建以固定间隔运行的作业?

时间:2015-06-05 17:01:56

标签: reactive-programming rx-java

我尝试创建一个定期查询我的数据库的任务,将所有结果写入另一个状态,并且我想使用RxJava执行此操作。

我使用RxJava-JDBC查询我的数据库。这是代码的样子:

    final Database db = Database.from(url);

    db
        .select("SELECT f1,f2 FROM mydata")
        .autoMap(MyDatum.class)
        .subscribe(
            new Action1<MyDatum>() {
                @Override
                public void call(MyDatum t) {
                    state.add(t);
                }
            },
            new Action1<Throwable>() {
                @Override
                public void call(Throwable t) {
                    L.error("Task failed", t);
                }
            },
            new Action0() {
                @Override
                public void call() {
                    state.makeAvailable();
                }
            }
        );

当我订阅它然后它停止时,这是有效的。所以我使用Observable.interval并使其工作:

    Observable
        .interval(10, TimeUnit.SECONDS)
        .forEach(
            new Action1<Long>() {
                @Override
                public void call(Long arg) {
                    db
                        .select("SELECT f1,f2 FROM mydata")
                        .autoMap(MyDatum.class)
                        .subscribe(
                            new Action1<MyDatum>() {
                                @Override
                                public void call(MyDatum t) {
                                    state.add(t);
                                }
                            },
                            new Action1<Throwable>() {
                                @Override
                                public void call(Throwable t) {
                                    L.error("Task failed", t);
                                }
                            },
                            new Action0() {
                                @Override
                                public void call() {
                                    state.makeAvailable();
                                }
                            }
                        );
                }
            }
        );

但是我想知道我是否做错了将流嵌套在另一个中。 我考虑过使用flatMap,但onComplete永远不会被执行,因为interval从不调用onComplete

我希望它能够进化并且不仅可以通过间隔而且可以通过传入事件来触发。

我在这里遗漏了什么吗? 感谢

2 个答案:

答案 0 :(得分:1)

flatMapmerge是您要使用的运算符。首先,您应该避免在运算符的主体中订阅observable。而是使用flatMap并返回observable。这将为您订阅所有发出的可观测量。

为了手动触发查询,您可以合并PublishSubjectdocumentation),您可以调用onNext来推送事件并手动触发查询。将您的代码更改为类似的内容。

PublishSubject<Long> subject = PublishSubject.create();
Observable.merge(subject, Observable.timer(0, 1, TimeUnit.SECONDS))
    .flatMap(new Func1<Long, Observable<MyDatum>>() {
        @Override
        public Observable<MyDatum> call(Long arg) {
            return db
                .select("SELECT f1,f2 FROM mydata")
                .autoMap(MyDatum.class);
    }}).subscribe(
        new Action1<MyDatum>() {
            @Override
            public void call(MyDatum t) {
                state.add(t);
            }
        },
        new Action1<Throwable>() {
            @Override
            public void call(Throwable t) {
                L.error("Task failed", t);
            }
        },
        new Action0() {
            @Override
            public void call() {
                state.makeAvailable();
            }
        }
    );
// you can call onNext with any value to trigger a manual query
subject.onNext(999L);

这是一个演示此行为的简单RxJava代码段。

CountDownLatch l = new CountDownLatch(5);
PublishSubject<Long> subject = PublishSubject.create();
Observable.merge(subject, Observable.timer(0, 1, TimeUnit.SECONDS).take(3))
        .flatMap((Long arg) -> {
            System.out.println("tick: " + arg);
            l.countDown();
            return Observable.just(arg+10);
        })
        .forEach(System.out::println);
l.await(1, TimeUnit.SECONDS);
subject.onNext(999L);
l.await();

<强>输出

tick: 0
10
tick: 999
1009
tick: 1
11
tick: 2
12

答案 1 :(得分:1)

Before: 2015-06-08T15:57:00Z Now: 2015-06-08T16:07:08.893Z After: 2015-06-08T16:17:08.893Z put items { Item: {hashAttributeName=1, dateField=2015-06-08T15:57:00Z} } { Item: {hashAttributeName=2, dateField=2015-06-08T16:07:08.893Z} } expected conditional write with < to fail when they are equal expected conditional write with < to fail when new is before after all updates { Item: {hashAttributeName=1, dateField=2015-06-08T15:57:00Z} } { Item: {hashAttributeName=2, dateField=2015-06-08T16:17:08.893Z} } doOnNext运算符在您的情况下非常有用。以下是如何使用这些运算符实现所描述的行为的示例:

doOnCompleted