Zaman aşımı değeri ile eşzamanlı olarak eşzamansız istek nasıl çağrılır?
Zaman uyumsuz bir API isteğini eşzamanlı olarak çağırmam gerekiyor. Bu api isteğinin yanıtlanması uzun zaman aldığından, api-isteğinin başarısız olması ve null ile devam etmesi için bir zaman aşımı ayarlamak istiyorum. İşte bu api'yi aramak için kodum:
private suspend fun call(
accessStage: AccessStage,
): Response? = withContext<Response?>(Dispatchers.IO) {
return@withContext withTimeoutOrNull(1000) {
suspendCoroutine<Response?> { continuation ->
val request = External3rdPartyApi.newRequest(
accessStage
) { response, throwable ->
continuation.resume(response)
}
request.parameters = hashMapOf<String, String>().apply {
put["token"] = External3rdPartyApi.TOKEN
put["salt"] = External3rdPartyApi.calculateSalt(accessStage)
}
request.executeAsync()
}
}
}
Nasıl External3rdPartyApi
çalıştığını değiştiremem .
Bence yukarıdaki kod kötü görünüyor. Ayrıca başka bir cevapta okudum :
withTimeout { ... }
yalnızca söz konusu işlem iptal edilebilirse mümkün olan zaman aşımıyla devam eden işlemi iptal etmek için tasarlanmıştır .
Öyleyse, suspendCancellableCoroutine
yerine kullanmalı suspendCoroutine
mıyım?
Nasıl daha iyi yazabilirim?
Yanıtlar
Kullanımı suspendCoroutine
gayet eğer eşyordamın değil (ya istemiyorum) kolu iptali can. Ancak bir zaman aşımınız olduğu için, suspendCancellableCoroutine'i kullanmayı düşünmeli ve işi durdurmak için cancelation olayını işlemelisiniz (mümkünse üçüncü taraf işlevinde).
suspendCancellableCoroutine<T> { continuation ->
continuation.invokeOnCancellation { throwable ->
// now you could stop your (third party) work
}
}
Üçüncü taraf işleviniz bir istisna attığında, onu yakalamayı deneyebilir ve ile devam ettirerek exception
veya bir null
değer döndürerek devam ettirmeyi bitirebilirsiniz (kullanım durumunuza bağlıdır):
suspendCancellableCoroutine<T?> { continuation ->
try {
continuation.resume(thirdParty.call())
} catch (e: Exception) {
// resume with exception
continuation.resumeWithException(e)
// or just return null and swallow the exception
continuation.resume(null)
}
}
Hepsini bir araya getirelim
suspend fun call(): Response? = withContext(Dispatchers.IO) {
return@withContext withTimeoutOrNull(1000L) {
return@withTimeoutOrNull suspendCancellableCoroutine { continuation ->
try {
continuation.resume(External3rdPartyApi.newRequest(accessStage))
} catch (e: Exception) {
// resume with exception
continuation.resumeWithException(e)
// or just return null and swallow the exception
continuation.resume(null)
}
// in case the coroutine gets cancelled - because of timeout or something else
continuation.invokeOnCancellation {
// stop all the work
}
}
}
}