使用`Observable`s实现速率受限的搜索结果

时间:2017-05-15 09:20:15

标签: rx-java system.reactive

我们说我有两个Observable s:
obs1在搜索框中发出用户输入结果,
obs2将字符串作为输入并启动HTTP请求,然后提供结果

现在,我想限制HTTP请求的数量不是一些恒定的时间间隔,而是取决于当前请求obs2完成的时间,如下所示:

  1. 用户类型tobs2会立即使用t
  2. 启动请求
  3. 用户类型teobs2仍然是#34;忙碌",没有任何反应
  4. 用户类型tesobs2仍然是#34;忙碌",没有任何反应
  5. 用户类型testobs2仍然是#34;忙碌",没有任何反应
  6. t - HTTP响应已经到达,obs2现在是#34;免费",它查看obs1上次发布的值并找到test,开始新请求
  7. test - HTTP响应已经到达,obs2现在是#34;免费",它查看obs1上次发布的值并找到test,没有,因为价值没有改变。
  8. 我可以通过引入额外的变量来表明系统的状态和搜索查询累加器,但我想知道这是否可以用纯函数方式完成,即仅使用rxJava方法?

1 个答案:

答案 0 :(得分:1)

查看代码和评论。

import rx.Observable;
import rx.schedulers.Schedulers;
import rx.subjects.PublishSubject;
import xdean.jex.extra.Pair;

public class Q43975663 {
  public static void main(String[] args) throws InterruptedException {
    PublishSubject<String> textSub = PublishSubject.create(); // emit user input text
    PublishSubject<String> taskSub = PublishSubject.create(); // emit when execution thread is free
    // core
    Observable
        // when new text input or execution thread change to free, emit an item
        .combineLatest(textSub.distinctUntilChanged(), taskSub, Pair::of)
        // if the text not change or task cycle not change, ignore it
        .scan((p1, p2) ->
            (p1.getLeft().equals(p2.getLeft()) || p1.getRight().equals(p2.getRight())) ?
                p1 : p2)
        .distinctUntilChanged()
        // map to user input text
        .map(Pair::getLeft)
        // scheduler to IO thread
        .observeOn(Schedulers.io())
        // do HTTP request
        .doOnNext(Q43975663::httpTask)
        // emit item to notify the execution thread is free
        .doOnNext(taskSub::onNext)
        .subscribe();
    // test
    taskSub.onNext("start");
    textSub.onNext("t");
    textSub.onNext("te");
    textSub.onNext("tex");
    textSub.onNext("text");
    Thread.sleep(5000);
    textSub.onNext("new");
    textSub.onNext("new");
    textSub.onNext("text");
    Thread.sleep(5000);
  }

  static void httpTask(String id) {
    System.out.printf("%s \tstart on \t%s\n", id, Thread.currentThread());
    try {
      Thread.sleep((long) (Math.random() * 1000));
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.printf("%s \tdone on \t%s\n", id, Thread.currentThread());
  }
}

注意Pair是一个简单的类,有两个值,左和右。

输出:

t       start on    Thread[RxIoScheduler-2,5,main]
t       done on     Thread[RxIoScheduler-2,5,main]
text    start on    Thread[RxIoScheduler-2,5,main]
text    done on     Thread[RxIoScheduler-2,5,main]
new     start on    Thread[RxIoScheduler-2,5,main]
new     done on     Thread[RxIoScheduler-2,5,main]
text    start on    Thread[RxIoScheduler-2,5,main]
text    done on     Thread[RxIoScheduler-2,5,main]