https://kotlinlang.org logo
#coroutines
Title
# coroutines
t

Tran Thang

02/22/2023, 12:47 PM
have 3 api as below:
Copy code
class MovieRepositoryImpl(private val api: MovieApi):MovieRepository {
    override suspend fun fetchMovie(): Movie {
      return api.fetchMovie()
    }

    override suspend fun fetchMoviePopular(): MoviePopular {
       return api.fetchMoviePopular()
    }

    override suspend fun fetchFaves(): Faves {
        return api.fetchFaves()
    }
}
I am wanting to call the above 3 api at the same time with the following condition: if the 1st api fails, the following 2 apis will not be called, but if the 1st api succeeds, the 2nd api fails, still call the 3rd API In short, if the 1st api fails, don't call the rest of the apis, but if the 2nd api fails, continue to call other apis
Copy code
fun fetchAll():Triple<Movie,MoviePopular,Faves> = supervisorScope {
        val movieDeferred = async { fetchMovie() }
        val moviePopularDeferred = async { fetchMoviePopular() }
        val favesDeferred = async { fetchFaves() }
        val movie = movieDeferred.await()
        val moviePopular = moviePopularDeferred.await()
        val faves = favesDeferred.await()
        return@supervisorScope Triple(movie,moviePopular,faves)
    }
so can anyone help me to solve this problem.
s

s3rius

02/22/2023, 5:13 PM
I am wanting to call the above 3 api at the same time with the following condition: if the 1st api fails, the following 2 apis will not be called,
I don't see how you can do both of these things. Either you • Call all three at the same time, or • You call 1st, wait for its result (or failure) and then decide if you want to call the other two. I'm guessing you're looking for the second option. Personally, I'd write something like this
Copy code
supervisorScope {
	// run the first call regularly to see if it fails
	val movie = try { fetchMovie() } catch (e: Exception) { null } ?: return@supervisorScope null

	// then start the other two in sync
	val popular = async {
		try { fetchPopular() } catch (e: Exception) { null }
	} 
	val faves = async {
		try { fetchFaves() } catch (e: Exception) { null }
	}

    // finally await both results
	// popular and faves are nullable because they could fail.
	Triple(movie, popular.await(), faves.await())
}
This assumes that all API calls fail by throwing an exception.
However, there is one subtle bug that may sometimes happen. If a coroutine is cancelled it will throw a
CancellationException
. This exception gets caught by these try-blocks as well. But these exceptions should not be caught, instead they should be propagated. So technically all try-blocks should check if an exception
is CancellationException
and re-throw it.
7 Views