Hello. We need to make a single API call from diff...
# coroutines
r
Hello. We need to make a single API call from different places and share the result from API response. And we need to suspend for the result because the one who is trigger the API call is not us but the core “module” (they kinda ask us for information and we should provide it to them) So far we have a following solution:
Copy code
class Repo {
  var currentJob: Deferred<Response> = null

  suspend fun loadData(): Response = coroutineScope {

    if (currentJob.isActive) {
      return@coroutineScope currentJob.await()
    }

    currentJob = async { makeRequest() }

    return@coroutineScope currentJob.await()
  }
}
So we want to call
loadData
multiple times from the different places but make only one request (
makeRequest()
) if they were called at the same time. Is it okay to call await several times? Is there a better solution?
s
I'd wrap this code within a Mutex to avoid race conditions. And I'd cache the value instead of Deferred of the value, this way you don't need to use
async
Assuming "null" is not a valid value, a Repo instance would have a field "var response: Response? = null" and a field "val Mutex = Mutex()". The loadData method would obtain/lock the Mutex. While locked, if "response" is null, return "response" after releasing the Mutex, otherwise call makeRequest and assign that to "response", release the Mutex lock and return "response".
^^^ My answer assumes you only want to have a max of 1 "makeRequest" calls at the same time, never more than one.
r
Thanks for you answer 🙂 I totally forgot about Mutex 🙂 but I have a question at which point I should clear that cached response? Because we would like to make this call again after some time to update the data without killing the app. And yes, when it is triggered it is always triggered form different(two) places
s
For clearing the cached response: That depends on your use case. I'd launch a timer (using delay(.....)) when just after the
makeRequest()
call that would set the response back to
null
. Be sure to also lock that Mutex while clearing that cached response.
b
Keep in mind that your
loadData()
call won't complete, because you will suspend on
coroutineScope
until all child coroutines complete, and that includes your
async {}
call there.