首页 > 解决方案 > 在不阻塞线程的情况下等待 Kotlin 协程中的 Java 5 Futures

问题描述

我有一个suspend函数,我想从中返回 Java 5 的结果Future。未来对象来自另一个库Firebase Cloud Firestore- Admin SDK for Java,并提供阻塞调用get()来检索所述未来的结果。

我的功能看起来像这样-

suspend fun getPrefix(messageCreateEvent: MessageCreateEvent): String {

    val snapshot = db.collection("prefixes")
        .document(messageCreateEvent.guildId.get().asString())
        .get() //This returns a future
        .get() //Retrieves the future's result (Blocks thread; IDE gives warning)

    //Return the prefix
    return if (snapshot.exists())
        snapshot.getString("prefix") ?: DEFAULT_PREFIX
    else DEFAULT_PREFIX
}

我考虑过的解决方案

我考虑的第一件事是寻找kotlinx.coroutine扩展来连接未来。虽然存在扩展,但它们仅适用于CompletionStatge. 所以我决定把未来包装成一个()——

val snapshot = CompleteableFuture.supplyAsync {
    db.collection("prefixes")
        .document(messageCreateEvent.guildId.get().asString())
        .get() // This returns a future
        .get() // Get the result
}.await()

我非常缺乏经验,不确定这是否是正确的解决方案。我在一个编程社区上询问了我的问题,有人建议我使用Deferred-

val deferred = CompletableDeferred<DocumentSnapshot>()
val future = db.collection("prefixes")
    .document(messageCreateEvent.guildId.get().asString())
    .get()

future.addListener(
    Runnable { deferred.complete(future.get()) },
    ForkJoinPool.commonPool()
)
            
val snapshot = deferred.await()

我已经花了相当长的时间来寻找一种将未来连接到协同程序的方法,甚至没有类似的问题。通过,如果这个问题得到重复标记,我不会感到惊讶。

标签: javakotlingoogle-cloud-firestoreconcurrencykotlin-coroutines

解决方案


您可以使用它kotlinx-coroutines-guava来执行此操作

首先转换ApiFutureListenableFuture使用,ApiFutureToListenableFuture然后使用.await以等待 listenableFuture 完成而不阻塞线程。

ApiFutureToListenableFuture(this).await()

推荐阅读