如何等待函数调用?

How To await a function call?

所以我发生了一些异步操作,我可以创建一些 lambada,调用一个函数并将该值传递给它们。但是我想要的不是把运算的结果作为参数,我要return他们

例如,我有一个 class A 和一些听众,如果有结果,所有听众都会收到通知。所以基本上 asyncFunction 应该 return 一个结果,否则会被暂停。

object A {
    val listeners = mutableListOf<(Int) -> Unit>()

    fun onResult(value: Int) {
        listeners.forEach { it(value) }
    }
}

fun asyncFunction(): Deferred<Int> {
    return async {
        A.listeners.add({ result ->

        })

        return result
    }
}

我现在在想的(也许我完全走错了路)是有一个类似 Deferred 的东西,我可以将结果发送到它 returns。有类似的东西吗?我可以自己实现 Deffered 吗?

class A {
    private val awaiter: ??? // can this be a Deferred ?

    fun onResult(result: Int) {
        awaiter.putResult(result)
    }

    fun awaitResult(): Int  {
        return awaiter.await()
    }
}

val a = A()

launch {
    val result = a.awaitResult()
}

launch {
    a.onResult(42)
}

所以我知道通过回调可以处理这个问题,但这样会更干净、更容易。

我希望我只是缺少一个漂亮干净的解决方案。

您的 asyncFunction 实际上应该是一个可挂起的函数:

suspend fun suspendFunction(): Int =
    suspendCoroutine { cont -> A.listeners.add { cont.resume(it) } }

请注意,它 returns Int 结果并暂停直到它可用。

但是,这只是解决您当前问题的方法。它仍然会在很多方面出现故障:

  • 一旦获得第一个结果,监听器的目的就达到了,但它永远停留在监听器列表中,导致内存泄漏
  • 如果结果在您调用 suspendFunction 之前到达,它将错过并挂起。

您可以继续手动改进它(这是一种很好的学习方式),或者切换到标准库提供的可靠解决方案。库解为CompletableDeferred:

object A {
    val result = CompletableDeferred<Int>()

    fun provideResult(r: Int) {
        result.complete(r)
    }
}

suspend fun suspendFunction(): Int = A.result.await()