我想弄清楚Kotlin是否可以替代我们当前处理异步代码的方式。现在,我们使用CompletableFutures
处理异步代码。这是这种方法的示例:
public void onBalanceRequest(Client client, String name) {
db.fetchBalance(name)
.thenAccept(balance -> {
client.sendMessage("Your money: " + balance);
});
}
这里重要的一点是onBalanceRequest
是从主线程调用的,不能被阻塞。在内部,db.fetchBalance
运行异步操作并在完成时解决将来的问题,因此给定的调用不会阻塞主线程。
在阅读了有关协同程序的Kotlin文档之后,我希望我们可以做一些像JavaScript的async / await之类的事情。例如,这是我们可以在JavaScript中执行的操作:
async function onBalanceRequest(client, name) {
let balance = await db.fetchBalance(name);
client.sendMessage("Your money: " + balance);
}
现在,我尝试将现有的API连接到Kotlin项目:
private fun onBalanceRequest(client: Client) = runBlocking {
val money = db.fetchBalance(client.name)
client.sendMessage("Your money: $money")
}
suspend fun fetchBalance(player: String): Double? {
var result: Double? = null
GlobalScope.launch {
originalFetchBalance(player).thenAccept {
result = it
}
}.join()
return result
}
但是,由于我使用了runBlocking
,因此onBalanceRequest
的执行阻塞了主线程。因此,如果您可以通过Kotlin实现类似于async / await的功能,请问您。
谢谢。
答案 0 :(得分:4)
如果您的JS函数为async
,则相应的Kotlin函数应为suspend
:
private suspend fun onBalanceRequest(client: Client) {
val money = db.fetchBalance(client.name)
client.sendMessage("Your money: $money")
}
不需要await
,因为Kotlin是静态类型的,并且编译器已经知道哪些函数是suspend
并且需要特殊对待(尽管C#(也是静态类型的)使用{{ 1}} / async
模型的明确性。
请注意,只能直接从await
函数中调用它;如果您想“抛弃”它,请使用suspend
:
launch
要使用private fun onBalanceRequest(client: Client) = GlobalScope.launch {
val money = db.fetchBalance(client.name)
client.sendMessage("Your money: $money")
}
返回函数,请使用kotlinx-coroutines-jdk8:
CompletableFuture
答案 1 :(得分:2)
当然runBlocking
将被阻止。因此,请改用launch
。
private fun onBalanceRequest(client: Client) = GlobalScope.launch {
val money = db.fetchBalance(client.name)
client.sendMessage("Your money: $money")
}
要桥接CompletableFuture
,可以先使用CompletableDeferred
suspend fun fetchBalance(player: String): Double {
val async = CompletableDeferred()
originalFetchBalance(player).whenComplete { (value, error) ->
if (value != null) async.complete(value)
if (error != null) async.completeExceptionally(error)
}
return async.await()
}