如何处理RxJava中多个链式Observable的错误?

时间:2018-11-22 06:54:31

标签: android rx-java reactive-programming rx-android

我正在使用Kotlin,RxJava和Retrofit开发一个Android应用程序。 我想将Http请求发送到服务器。

  1. PUT-作业的更新选项
  2. POST-运行作业

第一个请求成功后,我发送第二个请求。 所以我用了concatMap。

val updateJob = restService.updateJob(token, job.id, options) // PUT
val runJob = restService.runJob(token, job.id) // POST

updateJob.concatMap { runJob }
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ job ->
        Log.d(TAG, "runJob - success: $job")
    }, {
        Log.e(TAG, "runJob - failed: ${it.message}")
        it.printStackTrace()
    })

如果第一个请求失败,我想取消。 我该怎么办?

这是可能的代码。 但是...这段代码是...我认为这很丑... 请问有没有很酷的代码?

disposable.add(
            restService.updateJob(token, job.id, options)    // PUT
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ job ->
                    Log.d(TAG, "updateJob - success")
                    restService.runJob(token, job.id)    // POST
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe({ job ->
                            Log.d(TAG, "runJob - success")
                        }, {
                            Log.e(TAG, "runJob - failed: ${it.message}")
                            it.printStackTrace()
                        })
                }, {
                    Log.e(TAG, "updateJob - failed: ${it.message}")
                    it.printStackTrace()
                })
        )

我还有一个问题。 我有工作清单。 我想做同样的事情。 即使某些作业失败,我也想继续下一个作业。 我考虑了“ onErrorResumeNext,onErrorReturn,doOnError”。 但是它们不是解决方案。 我该怎么办?

Observable.fromIterable(jobs)
            .concatMap { job ->
                val updateJob = restService.updateJob(token, job.id, options)
                val printJob = restService.printJob(token, job.id)

                updateJob.concatMap { printJob }
            }
            .window(1)    // I thought "window" can be the solution. But it doesn't work.
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({ job ->
                Log.d(TAG, "runJobs - success")

            }, {
                Log.e(TAG, "runJobs - failed: ${it.message}")
                it.printStackTrace()
            })

1 个答案:

答案 0 :(得分:1)

实际上,您已经给出了答案。 您的第一种情况是正确的

val updateJob = restService.updateJob(token, job.id, options) // PUT
val runJob = restService.runJob(token, job.id) // POST

updateJob.concatMap { runJob }
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ job ->
        Log.d(TAG, "runJob - success: $job")
    }, {
        Log.e(TAG, "runJob - failed: ${it.message}")
        it.printStackTrace()
    })

因此,在这种情况下,如果updateJob请求失败,则流将移至error stream,而runJob请求将永远不会被调用。

runJob仅在updateJob成功时才会被调用。

updateJob成功后,如果runJob失败,那么也会调用error stream

您不需要第二种解决方案。

对于第二个问题,onErrorResumeNext应该起作用。返回任何哑数值,并在onNext

中进行处理
Observable.fromIterable(jobs)
                    .concatMap { job -> restService.updateJob(token, job.id, options).onErrorResumeNext(Flowable.just(/*Send any dummy value*/)) }
                    .contcatMap { job -> restService.printJob(token, job.id).onErrorResumeNext{Flowable.just(/*Send any dummy value*/)} }
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe({ job ->
                        /*If dummy value received....handle it gracefully*/
                        Log.d(TAG, "runJobs - success")

                    }, {
                        Log.e(TAG, "runJobs - failed: ${it.message}")
                        it.printStackTrace()
                    })