https://kotlinlang.org logo
#rx
Title
# rx
n

Nikola Milovic

02/27/2020, 3:17 PM
I have to beg people here who might have an elegant solution to this callback hell.. https://stackoverflow.com/questions/60431813/combining-multiple-firebase-callbacks-with-rxjava2
k

kioba

02/27/2020, 6:05 PM
it’s not hell, you just trying to burn the forest around yourself. 🔥 give me a couple of minutes and I take a look
first mistake:
loadDrillTypes
if the stream fails it closes we can’t iterate on the documents any more. We need to move the loop insude the try:
Copy code
fun loadDrillTypes(): Observable<DrillsType> = 
  Observable.create<DrillsType> { emitter ->
    firebaseFirestore.collection("drilltypes")
      .get()
      .addOnSuccessListener { documents ->
        try {
          for (document in documents) {
            val doc = document.toObject(DrillsType::class.java)
            emitter.onNext(doc)
          }
        } catch (e: Exception) {
          emitter.onError(e)
        }
          emitter.onComplete()
      }
      .addOnFailureListener { exception ->
          Log.w("TAG", "Error getting documents: ", exception)
          emitter.onError(exception)
      }
  }
You sould use flatmap:
Copy code
remoteDataSource
  .loadDrillTypes()
  .flatMap { data ->
    getImageUrl(data.drillType_imageUrl)
      .map{ 
         data.copy(drillType_imageUrl = it)
       }
  }
n

Nikola Milovic

02/27/2020, 9:18 PM
@kioba thanks for giving me these pointers! It seems so much more elegant. Can you elaborate on the second part with the flatmap? I've looked into it but cannot get it to work. And honestly don't quite get how this works the way it should.
m

Matej Drobnič

02/28/2020, 6:18 AM
I've answered you on the SO
p

pg

02/28/2020, 8:02 AM
You can also check how was it done by other people, for instance this little Rx Firebase wrapper lib. Maybe you will be inspired 😆 https://github.com/FrangSierra/RxFirebase
n

Nikola Milovic

02/28/2020, 9:46 PM
Thank you guys! This was the winning solution
Copy code
fun loadFullDrillType(): Observable<DrillsType> {
        return loadDrillTypeWithRawImageUrl().flatMapSingle { rawImageUrl ->
            loadImageUrl(rawImageUrl.drillType_imageUrl).map {
                return@map rawImageUrl.copy(drillType_imageUrl = it)
            }
        }
    }
Also used your @kioba try and catch fix for callbacks and documents. Thanks everyone ❤️ Didn't know that there was such a concise and simple solution to this problem.
@Matej Drobnič Just a quick note, how do you throw exceptions this way? It seems that if the datasources emit error it doesn't get pushed to the top. But rather nothing happens.
m

Matej Drobnič

02/29/2020, 4:38 PM
If the wrapper is implemented properly, then all exceptions should propagate up the stack normally and end up in
onError
method of original subscriber
👍 1