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