RxJava: upstream never completes when error is swallowed

☆樱花仙子☆ 提交于 2019-12-01 13:04:06

Your problem is that Single can only result in two values, a successful result or a failure. Turning the failure in an 'ignored' state can be done by first converting it to a Maybe and then using essentially the same code to handle failure and success.

Maybe.onErrorResumeNext with a return value of Maybe.empty() would result in 0 or 1 results while Maybe.map only executes if it has a value, accurately handling the problem as you've described it.

Adapted code:

        .flatMapMaybe { file ->
            uploadFile(file).toMaybe()
                    .onErrorResumeNext { error: Throwable ->
                        log(error)
                        Maybe.empty()
                    }
                    .map { response ->
                        file.id = response.id
                        file
                    }
        }

Here is how I have handled it in the past by using the zip method.

  // create an observable list that you can process for you file uploads
  val responses: Response = listOf<Response>()

  queryFiles()?.let { file ->

    val observable = Observable.create(ObservableOnSubscribe<Response> { emitter ->
      // you can modify this section to your data types
      try {
        // with your uploadFile method you might be able to just add them
        // all the responses list
        emitter.onNext(uploadFile(file))
        emitter.onComplete()
      } catch (e: Exception) {
        emitter.onError(e)
      }
    }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
    responses.add(observable)    
  }

  // i setup a simple booleanArray to handle success/failure but you can add
  // all the files that fail to a list and use that later    
  val isSuccessful = booleanArrayOf(true)
  Observable.zip<Response, Boolean>(responses, Function<Array<Any>, Boolean> { responses ->
    var isSuccessful: Boolean? = java.lang.Boolean.TRUE
    // handle success or failure
    isSuccessful
  }).subscribe(Consumer<Boolean> { aBoolean -> isSuccessful[0] = aBoolean!! }, Consumer<Throwable> { throwable ->
    isSuccessful[0] = false
  }, Action {
    // handle your OnComplete here
    // I would check the isSuccessful[0] and handle the success or failure        
  })

This is creating all your uploads into a list of Observables that can be handled and merged with the zip method. This will merge them all when they are done into an array of any so that you can loop over them - your result from the uploadFile() method. This example is checking for a success or failure from the responses that come back. I removed most of the logic where the comment // handle success or failure is. In the function method you can keep track of your file uploads that fail or succeed.

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