2017-10-22 14 views
5

coroutines मैं विस्तार विधि का उपयोग कर इसघातीय कैसे backoff kotlin पर पुन: प्रयास

public suspend fun <T : Any> Call<T>.await(): T { 

    return suspendCancellableCoroutine { continuation -> 

    enqueue(object : Callback<T> { 

     override fun onResponse(call: Call<T>?, response: Response<T?>) { 
      if (response.isSuccessful) { 
       val body = response.body() 
       if (body == null) { 
        continuation.resumeWithException(
          NullPointerException("Response body is null") 
        ) 
       } else { 
        continuation.resume(body) 
       } 
      } else { 
       continuation.resumeWithException(HttpException(response)) 
      } 
     } 

     override fun onFailure(call: Call<T>, t: Throwable) { 
      // Don't bother with resuming the continuation if it is already cancelled. 
      if (continuation.isCancelled) return 
      continuation.resumeWithException(t) 
     } 
    }) 

     registerOnCompletion(continuation) 
    } 
} 

की तरह पुराना वापस में वर्ग कॉल करने के लिए नेटवर्क अनुरोध के लिए coroutines kotlin उपयोग कर रहा हूँ तो पक्ष बुला मैं इस

की तरह विधि से ऊपर का उपयोग कर रहा से
private fun getArticles() = launch(UI) { 

    loading.value = true 
    try { 
     val networkResult = api.getArticle().await() 
     articles.value = networkResult 

    }catch (e: Throwable){ 
     e.printStackTrace() 
     message.value = e.message 

    }finally { 
     loading.value = false 
    } 

} 

मैं कुछ मामलों में इस एपीआई कॉल को घातीय करना चाहता हूं यानी (आईओएक्सप्शन) मैं इसे कैसे प्राप्त कर सकता हूं ??

उत्तर

22

मैं आपके पुनः प्रयास तर्क के लिए एक सहायक higher-order function लिखने का सुझाव दूंगा। आप एक शुरू करने के लिए निम्नलिखित कार्यान्वयन का उपयोग कर सकते हैं:

suspend fun <T> retryIO(
    times: Int = Int.MAX_VALUE, 
    initialDelay: Long = 100, // 0.1 second 
    maxDelay: Long = 1000, // 1 second 
    factor: Double = 2.0, 
    block: suspend() -> T): T 
{ 
    var currentDelay = initialDelay 
    repeat(times - 1) { 
     try { 
      return block() 
     } catch (e: IOException) { 
      // you can log an error here and/or make a more finer-grained 
      // analysis of the cause to see if retry is needed 
     } 
     delay(currentDelay) 
     currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay) 
    } 
    return block() // last attempt 
} 

इस समारोह का उपयोग करना बहुत strightforward है:

val networkResult = retryIO { api.getArticle().await() } 

आप, मामला-दर-मामला आधार पर पुन: प्रयास मानकों को बदल सकते हैं, उदाहरण के लिए:

val networkResult = retryIO(times = 3) { api.doSomething().await() } 

आप अपने आवेदन की ज़रूरतों के अनुरूप retryIO के कार्यान्वयन को पूरी तरह से बदल सकते हैं। उदाहरण के लिए, आप सभी पुनः प्रयास पैरामीटर को हार्ड-कोड कर सकते हैं, रीट्रीज़ की संख्या, डिफ़ॉल्ट परिवर्तन आदि पर सीमा से छुटकारा पा सकते हैं।

+0

वाह बहुत साफ उत्तर धन्यवाद –

+1

यह ऐसा कुछ था जो मेरे सिर के पीछे था कुछ दिन अब समाधान देखने में अच्छा लगा कि मैं कल्पना कर रहा था उससे ज्यादा जटिल नहीं है। मैं खुद से यह भी पूछ रहा था कि क्या इस सहायक समारोह को इनलाइन फ़ंक्शन के रूप में परिभाषित करना समझ में आता है। और आखिरी लेकिन कम से कम नहीं: एक संशोधित कैसे किया जाएगा, यदि आप उपयोगकर्ता को ऐसा करने के बाद केवल पुनः प्रयास निष्पादित करना चाहते हैं (उदाहरण के लिए। एक संवाद में)? –

+1

आरएक्स समाधान से भी ज्यादा क्लीनर: -ओ – kenyee

संबंधित मुद्दे