drake пре 4 година
родитељ
комит
0727344e48
1 измењених фајлова са 35 додато и 0 уклоњено
  1. 35 0
      net/src/main/java/com/drake/net/utils/ScopeUtils.kt

+ 35 - 0
net/src/main/java/com/drake/net/utils/ScopeUtils.kt

@@ -230,5 +230,40 @@ suspend fun <T, R> CoroutineScope.fastest(vararg deferredArray: DeferredTransfor
     return chan.receive()
 }
 
+/**
+ * 该函数将选择[deferredList]中的Deferred执行[Deferred.await], 然后将返回最快的结果
+ * 执行过程中的异常将被忽略, 如果全部抛出异常则将抛出最后一个Deferred的异常
+ *
+ * @see DeferredTransform 允许监听[Deferred]返回数据回调
+ * @param deferredList 一系列并发任务
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+@Suppress("SuspendFunctionOnCoroutineScope")
+suspend fun <T, R> CoroutineScope.fastest(deferredList: List<DeferredTransform<T, R>>): R {
+    val chan = Channel<R>()
+    val mutex = Mutex()
+    deferredList.forEach {
+        launch(Dispatchers.IO) {
+            try {
+                val result = it.deferred.await()
+                mutex.withLock {
+                    NetCancel.cancel(coroutineContext[CoroutineExceptionHandler])
+                    if (!chan.isClosedForSend) {
+                        val transformResult = it.block(result)
+                        chan.send(transformResult)
+                    }
+                }
+            } catch (e: Exception) {
+                it.deferred.cancel()
+                val allFail = deferredList.all { it.deferred.isCancelled }
+                if (allFail) throw e else {
+                    if (e !is CancellationException) e.printStackTrace()
+                }
+            }
+        }
+    }
+    return chan.receive()
+}
+