简体   繁体   English

RxJava:链接可观察量

[英]RxJava: chaining observables

Is it possible to implement something like next chaining using RxJava: 是否可以使用RxJava实现下一个链接:

loginObservable()
   .then( (someData) -> {
      // returns another Observable<T> with some long operation
      return fetchUserDataObservable(someData);

   }).then( (userData) -> {
      // it should be called when fetching user data completed (with userData of type T)
      cacheUserData(userData);

   }).then( (userData) -> {
      // it should be called after all previous operations completed
      displayUserData()

   }).doOnError( (error) -> {
      //do something
   })

I found this library very interesting, but can't figure our how to chain requests where each other depends on previous. 我发现这个库非常有趣,但无法想象我们如何将请求链接到彼此依赖于之前的地方。

Sure, RxJava supports .map which does this. 当然,RxJava支持.map这样做。 From the RxJava Wiki: 来自RxJava Wiki:

地图

Basically, it'd be: 基本上,它是:

loginObservable()
   .switchMap( someData -> fetchUserDataObservable(someData) )
   .map( userData -> cacheUserData(userData) )
   .subscribe(new Subscriber<YourResult>() {
        @Override
        public void onCompleted() {
           // observable stream has ended - no more logins possible
        }
        @Override
        public void onError(Throwable e) {
            // do something
        }
        @Override
        public void onNext(YourType yourType) {
            displayUserData();
        }
    });

This is the top post when Googling RxJava chain observables so I'll just add another common case where you wouldn't want to transform the data you receive, but chain it with another action (setting the data to a database, for example). 这是Googling RxJava链可观察量的最高职位,因此我将添加另一个常见情况,您不希望转换您收到的数据,但将其与另一个操作链接(例如,将数据设置为数据库)。 Use .flatmap() . 使用.flatmap() Here's an example 这是一个例子

    mDataManager.fetchQuotesFromApi(limit)
            .subscribeOn(mSchedulerProvider.io())
            .observeOn(mSchedulerProvider.ui())
            .onErrorResumeNext(Function { Observable.error<List<Quote>>(it) }) //OnErrorResumeNext and Observable.error() would propagate the error to the next level. So, whatever error occurs here, would get passed to onError() on the UI side
            .flatMap { t: List<Quote> ->
                //Chain observable as such
                mDataManager.setQuotesToDb(t).subscribe({}, { e { "setQuotesToDb() error occurred: ${it.localizedMessage}" } }, { d { "Done server set" } })
                Observable.just(t)
            }
            .subscribeBy(
                    onNext = {},
                    onError = { mvpView?.showError("No internet connection") },
                    onComplete = { d { "onComplete(): done with fetching quotes from api" } }
            )

This is RxKotlin2, but the idea is the same with RxJava & RxJava2: 这是RxKotlin2,但RxJava和RxJava2的想法是一样的:

Quick explanation: 快速解释:

  • we try to fetch some data (quotes in this example) from an api with mDataManager.fetchQuotesFromApi() 我们尝试使用mDataManager.fetchQuotesFromApi()从api获取一些数据(在本例中为引号mDataManager.fetchQuotesFromApi()
  • We subscribe the observable to do stuff on .io() thread and show results on .ui() thread. 我们订阅了observable来在.io()线程上做东西并在.ui()线程上显示结果。
  • onErrorResumeNext() makes sure that whatever error we encounter from fetching data is caught in this method. onErrorResumeNext()确保在此方法中捕获从获取数据中遇到的任何错误。 I wanna terminate the entire chain when there is an error there, so I return an Observable.error() 我想在那里出现错误时终止整个链,所以我返回一个Observable.error()
  • .flatmap() is the chaining part. .flatmap()是链接部分。 I wanna be able to set whatever data I get from the API to my database. 我希望能够将从API获得的任何数据设置到我的数据库中。 I'm not transforming the data I received using .map() , I'm simply doing something else with that data without transforming it. 我没有使用.map()转换我收到的数据,我只是在改变它的情况下使用该数据做其他事情
  • I subscribe to the last chain of observables. 我订阅了最后一个可观察链。 If an error occurred with fetching data (first observable), it would be handled (in this case, propagated to the subscribed onError() ) with onErrorResumeNext() 如果在获取数据时出现错误(第一个可观察的),则会使用onErrorResumeNext()处理它(在这种情况下,传播到订阅的onError() onErrorResumeNext()
  • I am very conscious that I'm subscribing to the DB observable (inside flatmap() ). 我非常清楚我正在订阅DB observable(在flatmap()内部)。 Any error that occurs through this observable will NOT be propagated to the last subscribeBy() methods, since it is handled inside the subscribe() method inside the .flatmap() chain. 通过此observable发生的任何错误都不会传播到最后的subscribeBy()方法,因为它是在.flatmap()链内的subscribe()方法内处理的。

The code comes from this project which is located here: https://github.com/Obaied/Sohan/blob/master/app/src/main/java/com/obaied/dingerquotes/ui/start/StartPresenter.kt 代码来自这个项目 ,位于: https//github.com/Obaied/Sohan/blob/master/app/src/main/java/com/obaied/dingerquotes/ui/start/StartPresenter.kt

尝试使用scan()

Flowable.fromArray(array).scan(...).subscribe(...)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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