Alfred Lopez
10/01/2021, 7:08 PMAlfred Lopez
10/01/2021, 7:09 PMmkrussel
10/01/2021, 7:16 PMCRamsan
10/01/2021, 7:16 PMBig Chungus
10/01/2021, 7:16 PMAlfred Lopez
10/01/2021, 7:18 PMBig Chungus
10/01/2021, 7:19 PMBig Chungus
10/01/2021, 7:21 PMAlfred Lopez
10/01/2021, 7:21 PMBig Chungus
10/01/2021, 7:21 PMAlfred Lopez
10/01/2021, 7:25 PMBig Chungus
10/01/2021, 7:26 PMAlfred Lopez
10/01/2021, 7:26 PMBig Chungus
10/01/2021, 7:26 PMCRamsan
10/01/2021, 7:27 PMAlfred Lopez
10/01/2021, 7:27 PMBig Chungus
10/01/2021, 7:28 PMCRamsan
10/01/2021, 7:29 PMephemient
10/01/2021, 7:42 PMsuspend fun main()
on JVM isn't exactly the same as fun main() = runBlocking { ... }
, due to challenges with kotlinx.coroutines.runBlocking
being in a separate library. instead it translates to kotlin.coroutines.jvm.internal.runSuspend
, which is simpler and doesn't set up the event-loop dispatcher that runBlocking
doesAlfred Lopez
10/04/2021, 12:49 PMBig Chungus
10/04/2021, 12:59 PMmain-safe
(i.e. switching to appropriate dispatcher for IO and other long-running tasks)Alfred Lopez
10/04/2021, 1:00 PMAlfred Lopez
10/04/2021, 1:00 PMBig Chungus
10/04/2021, 1:00 PMAlfred Lopez
10/04/2021, 1:01 PMBig Chungus
10/04/2021, 1:01 PMAlfred Lopez
10/04/2021, 1:01 PMAlfred Lopez
10/04/2021, 1:02 PMBig Chungus
10/04/2021, 1:02 PM// commonMain
suspend fun doStuff(arg1: Any) {...}
//jvmMain
fun doStuffBlocking(arg1: Any) = runBlocking{ doStuff(arg1) }
Alfred Lopez
10/04/2021, 1:02 PMAlfred Lopez
10/04/2021, 1:02 PMBig Chungus
10/04/2021, 1:03 PMBig Chungus
10/04/2021, 1:03 PMAlfred Lopez
10/04/2021, 1:03 PMBig Chungus
10/04/2021, 1:03 PMAlfred Lopez
10/04/2021, 1:03 PMBig Chungus
10/04/2021, 1:04 PMBig Chungus
10/04/2021, 1:04 PMAlfred Lopez
10/04/2021, 1:04 PMBig Chungus
10/04/2021, 1:04 PMmkrussel
10/04/2021, 1:04 PMAlfred Lopez
10/04/2021, 1:05 PMBig Chungus
10/04/2021, 1:05 PM// jsMain
fun doStuffPromise(arg1: Any) = GlobalScope.launch {doStuff(arg1)}.asPromise()
Big Chungus
10/04/2021, 1:06 PMmkrussel
10/04/2021, 1:06 PMAlfred Lopez
10/04/2021, 1:07 PMBig Chungus
10/04/2021, 1:08 PMBig Chungus
10/04/2021, 1:08 PMAlfred Lopez
10/04/2021, 1:09 PMBig Chungus
10/04/2021, 1:10 PMAlfred Lopez
10/04/2021, 1:10 PMAlfred Lopez
10/04/2021, 1:11 PMAlfred Lopez
10/04/2021, 1:12 PMBig Chungus
10/04/2021, 1:12 PMBig Chungus
10/04/2021, 1:12 PMAlfred Lopez
10/05/2021, 2:02 PMBig Chungus
10/05/2021, 2:24 PMAlfred Lopez
10/07/2021, 4:02 PMfun something() {
//do something
doSomethingElse()
}
fun doSomethingElse() = runBlockingCode{
//call some suspend features, etc.
}
where
//JS
val testScope = MainScope()
actual fun <T> runBlockingCode(block : suspend () -> T) : dynamic = testScope.apply { }.async(start = CoroutineStart.UNDISPATCHED) { block() }
and
//JVM
actual val coroutineContext : CoroutineContext =
Executors.newSingleThreadExecutor().asCoroutineDispatcher()
actual fun <T> runBlockingCode(block : suspend () -> T) =
runBlocking(coroutineContext) { block() }
and then I call doSomething()
like so...
//TypeScript
(async () => {
await this.myObject.doSomething();
//get result of doSomething() and do more TypeScripty stuff
}
the code in doSomething()
runs fine, but when it hits doSomethingElse()
, it merely gets the reference to the Promise, and not execute. I tried forcing the functions to execute immediately using CoroutineStart.UNDISPATCHED
, as you see above, but I'm not seeing the code run either.
So given the requirements, how would one go about swapping out `runBlocking`and using "normal" coroutines while achieving synchronicity in JVM and asynchronicity in JS?
Thanks!ephemient
10/07/2021, 4:17 PM// common
suspend fun doWork(): T = ...
// js
@JsExport
fun doWorkAsync(): Promise<T> = GlobalScope.promise { doWork() }
// jvm
fun doWorkAsync(): ListenableFuture<T> = GlobalScope.future { doWork() }
fun doWorkBlocking(): T = runBlocking { doWork() }
CRamsan
10/07/2021, 4:30 PMrunBlockingCode
actually does not run blocking code, the oposite, it runs suspending code. If your developers dont want to write suspending code, they can wrap a call to suspend fun doSomethingElse()
in a runBlocking or you could provide a JVM only wrapper like:
fun doSomethingElseBlocking() = runBlocking {
doSomethingElse()
}
With regards to your tests, in your JS code you are calling async (actual fun <T> runBlockingCode(block : suspend () -> T) : dynamic = testScope.apply { }.*async*(start = CoroutineStart.UNDISPATCHED) { block() }), which indeed returns a reference to the job. The github issue you linked has the right syntax. It should be something like testScope.promise { this.block() }
and that will run the promise in the testScope.Alfred Lopez
10/07/2021, 5:52 PMactual fun <T> runBlockingCode(block : suspend () -> T) =
runBlocking(coroutineContext) { block() }
Is the same as in the github post. Though, I do agree with you that it is running suspended code instead of blocking code. It would be nice if I could remove the suspend from the (block: suspend () -> T)
so that in the JS version, my function would be
actual fun <T> runBlockingCode(block : () -> T) : dynamic = block()
since JavaScript developers are used to async/await/Promise, but, of course, the compiler complains about calling suspend functions outside of a suspend or coroutine.Alfred Lopez
10/07/2021, 5:54 PMephemient
10/07/2021, 5:57 PMAlfred Lopez
10/07/2021, 5:58 PMAlfred Lopez
10/07/2021, 5:58 PMephemient
10/07/2021, 5:59 PMephemient
10/07/2021, 6:00 PMAlfred Lopez
10/07/2021, 6:01 PMAlfred Lopez
10/07/2021, 6:01 PMAlfred Lopez
10/07/2021, 6:03 PMAlfred Lopez
10/07/2021, 6:05 PMAlfred Lopez
10/07/2021, 6:06 PM