एक टाइमआउट मान के साथ अतुल्यकालिक अनुरोध को कैसे कॉल करें?
मुझे एक एसिंक्रोनस एपि अनुरोध को सिंक्रोनाइज़ करना है। चूंकि यह एपीआई अनुरोध का जवाब देने में लंबा समय लेता है, इसलिए मैं एपीआई-अनुरोध को विफल करने और अशक्त रहने के लिए एक समय निर्धारित करना चाहता हूं। यहाँ इस एपीआई को कॉल करने के लिए मेरा कोड है:
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()
}
}
}
मैं यह नहीं बदल सकता कि कैसे External3rdPartyApi
काम करता है।
मुझे लगता है कि ऊपर कोड बुराई लग रहा है। इसके अलावा, मैंने एक अन्य उत्तर में पढ़ा :
withTimeout { ... }
टाइमआउट पर चल रहे ऑपरेशन को रद्द करने के लिए डिज़ाइन किया गया है, जो केवल तभी संभव है जब प्रश्न में ऑपरेशन रद्द हो ।
तो, के suspendCancellableCoroutine
बजाय मैं का उपयोग करना चाहिए suspendCoroutine
?
मैं इसे बेहतर तरीके से कैसे लिख सकता हूं?
जवाब
का उपयोग करना suspendCoroutine
ठीक है अगर आप कर सकते हैं (या नहीं करना चाहते हैं) Coroutine का रद्दकरण। लेकिन क्योंकि आपके पास एक टाइमआउट है, तो आपको काम को रोकने के लिए सस्पेंड कांस्टेबलकोराटाइन का उपयोग करने पर विचार करना चाहिए और रद्द करने की घटना को संभालना चाहिए (तीसरे पक्ष के कार्य में - यदि आप कर सकते हैं)।
suspendCancellableCoroutine<T> { continuation ->
continuation.invokeOnCancellation { throwable ->
// now you could stop your (third party) work
}
}
जब आपका थर्ड पार्टी फंक्शन एक अपवाद फेंकता है, तो आप इसे आज़मा सकते हैं और अपना रेज्यूमे या तो फिर से शुरू कर सकते हैं या मान exception
वापस कर सकते हैं null
(आपके उपयोग मामले पर निर्भर करता है):
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)
}
}
चलो सब एक साथ डाल दिया
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
}
}
}
}