How to wait for async Observable to complete

匿名 (未验证) 提交于 2019-12-03 08:39:56

问题:

I'm trying to build a sample using rxjava. The sample should orchestrate a ReactiveWareService and a ReactiveReviewService retruning a WareAndReview composite.

ReactiveWareService         public Observable<Ware> findWares() {         return Observable.from(wareService.findWares());     }  ReactiveReviewService: reviewService.findReviewsByItem does a ThreadSleep to simulate a latency!  public Observable<Review> findReviewsByItem(final String item) { return Observable.create((Observable.OnSubscribe<Review>) observer -> executor.execute(() -> {     try {         List<Review> reviews = reviewService.findReviewsByItem(item);         reviews.forEach(observer::onNext);         observer.onCompleted();     } catch (Exception e) {         observer.onError(e);     } })); }  public List<WareAndReview> findWaresWithReviews() throws RuntimeException { final List<WareAndReview> wareAndReviews = new ArrayList<>();  wareService.findWares()     .map(WareAndReview::new) .subscribe(wr -> {         wareAndReviews.add(wr);         //Async!!!!         reviewService.findReviewsByItem(wr.getWare().getItem())             .subscribe(wr::addReview,                 throwable -> System.out.println("Error while trying to find reviews for " + wr)             );     } );  //TODO: There should be a better way to wait for async reviewService.findReviewsByItem completion! try {     Thread.sleep(3000); } catch (InterruptedException e) {}  return wareAndReviews; }

Given the fact I don't want to return an Observable, how can I wait for async Observable (findReviewsByItem) to complete?

回答1:

Most of your example can be rewritten with standard RxJava operators that work together well:

public class Example {      Scheduler scheduler = Schedulers.from(executor);      public Observable<Review> findReviewsByItem(final String item) {         return Observable.just(item)                .subscribeOn(scheduler)                .flatMapIterable(reviewService::findReviewsByItem);     }     public List<WareAndReview> findWaresWithReviews() {         return wareService                .findWares()                .map(WareAndReview::new)                .flatMap(wr -> {                    return reviewService                           .findReviewsByItem(wr.getWare().getItem())                           .doOnNext(wr::addReview)                           .lastOrDefault(null)                           .map(v -> wr);                })                .toList()                .toBlocking()                .first();     } }

Whenever you want to compose services like this, think of flatMap first. You don't need to block for each sub-Observable but only at the very end with toBlocking() if really necessary.



回答2:

You may use methods from BlockingObservable see https://github.com/Netflix/RxJava/wiki/Blocking-Observable-Operators. e.g

BlockingObservable.from(reviewService.findReviewsByItem(..)).toIterable()


回答3:

Another way would be to declare a CountdownLatch before starting. Then call countDown() on that latch in your onCompleted(). You can then replace your Thread.sleep() with await() on that latch.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!