How to call suspending function in class that implements an interface with non-suspending functions in Kotlin/JS

212 views Asked by At

I'm writing a Kotlin Multiplatform library using version 1.9.0-RC, and targeting JVM, Native, and JavaScript.

I want to create a class that implements an interface from a dependency.

// this interface comes from my project's dependency

interface ThirdPartyInterface {
  fun getData(): String
}

I want to fetch the result of getData() from a REST API, but this is implemented differently per target. As such, I've defined an expect fun so the implementation can be different for the JVM, Native, and JS targets.

expect suspend fun platformGetData(): String

When I try and use this function, I find that I'm not able to call it because there's no runBlocking {} implementation available in commonMain.

I'm also not able to use GlobalScope, because I don't just need to launch a suspending function, I also need to get the result.

// src/commonMain/kotlin/MyCommonClass.kt

import x.y.z.ThirdPartyInterface

class MyCommonClass : ThirdPartyInterface {

  override fun getData(): String {
    // can't use runBlocking, it's not available in commonMain
    // return runBlocking { platformGetData() }

    // I can use GlobalScope() to call the suspend fun...
    val result = GlobalScope().async { platformGetData() }
    // but then I can't read the result!
    result.await() // ERROR Suspend function 'await' should be called only from a coroutine or another suspend function
  }
}

Is there any way to work around this Kotlin/JS restriction?

While a multiplatform equivalent to runBlocking {} would work, I understand that this is not possible https://youtrack.jetbrains.com/issue/KT-29403.

I’m not necessarily looking for an equivalent to runBlocking {}, but even if there’s a JS-specific function that can bridge blocking/non-blocking then I could change the expect fun

//expect suspend fun getData(): String
expect fun getData(): String

and then in the actual fun use runBlocking {} on JVM/Native, and something else on JS.

I don’t mind if the Kotlin/JS code is limited by the inherently single threaded nature of JavaScript - just so long as I can write my code in commonMain, and bridge blocking/non-blocking however is practical for each target.

0

There are 0 answers