使用协程使函数返回在回调中获得的值

时间:2020-09-10 16:10:08

标签: kotlin kotlin-coroutines

我对异步开发和协程特别陌生。我要说的基本上是,我什至不知道我要实现的目标是否可行。

我有一个名为sendAudioMessage的方法,我想返回一个字符串。这是(模糊的)代码:

override suspend fun sendAudioMessage(): String {
   // ... Do some stuff
   val listener: WebSocketUtils.Listener = object: WebSocketUtils.Listener {
      // ... some (not relevant) functions
      override fun onDisconnect(code: Int, reason: String?) {
         //Do some stuff
         return "myResult -> $code" //This obviously doesn't compile since is trying to make onDisconnect return a string instead of Unit
      }
   }
}

然后我要这样称呼:

override fun send(request: String) {
    CoroutineScope(IO).launch {
        val response = d.sendAudioMessage()
        analyzeResponse( response, request )
    }
}

这甚至可能吗?如果是这样,我该如何实现?

1 个答案:

答案 0 :(得分:2)

您需要将回调包装在suspendCancellableCoroutine块中,以便将您的阻塞API调用转换为挂起函数,以便可以从协程调用它。它是这样的:

suspend fun sendAudioMessage(): String = suspendCancellableCoroutine { continuation ->
    WebSocketUtils.Listener {
        // ... some (not relevant) functions
        override fun onDisconnect(code: Int, reason: String?) {
            //Do some stuff
            when (code) {
                OK -> continuation.resume("myResult -> $code")
                ERROR -> continuation.resumeWithException(Exception(reason))
            }
        }
    }
}

当API调用成功返回时,您可以将结果返回给协程调用continuation.resume,并将结果作为参数。

当您的API调用返回错误时,您可以引发调用continuation.resumeWithException的异常。

现在您可以在协程中调用sendAudioMessage并照常使用其结果:

class MyClass: CoroutineScope by CoroutineScope(Dispatchers.Default) {
    
    ...
    
    override fun send(request: String) {
        launch(Dispatchers.IO) {
            val response = d.sendAudioMessage()
            analyzeResponse(response, request)
        }
    }
    
    ...
}