I’ve got a Java API that basically looks like this:
public class Client { void sendData(String message, Callback callback); // Enqueues data to send. void flush(); // Actually sends the data. public interface Callback { // Callback used once data has been sent. void onSuccess(int responseCode); void onFailure(Throwable error); } }
The callback thing is a huge pain (this is an over-simplification), and this will be used from Kotlin code, so I want to wrap it, but make it feel as native as I possible can. If I was working in Javascript I’d want my client library to look like this:
async function foo() { let clientWrapper = new ClientWrapper(); let a = clientWrapper.send("Hello"); let b = clientWrapper.send("World"); clientWrapper.flush(); let aResponse = await a; let bResponse = await b; return aResponse == 200 && bResponse = 200; }
My first attempt looked something like this:
class ClientWrapper { private val client = Client() suspend fun send(message: String) = suspendCoroutine { cont -> client.sendMessage(message, object : Callback { override fun onSuccess(responseCode: Int) { cont.resumeWith(responseCode) } override fun onFailure(error: Throwable) { cont.resumeWithException(error) } }) } } fun foo() { runBlocking { val clientWrapper = ClientWrapper() val aResponse = clientWrapper.send("Hello") val bResponse = clientWrapper.send("World") clientWrapper.flush() } }
This didn’t work very well. runBlocking
did what it says on the tin, and blocked on both send()
calls. Instead I want to be able to continue from send immediately, run flush()
and then block until I have both aResponse
and bResponse
.
Is there a clean way to do this in Kotlin?
submitted by /u/Shaftway
[link] [comments]