Hi @Alexey.Andreev,
that’s a totally reasonable response. I was info-dumping after a frustrating few hours last week but, if I got a bug report, I’d be asking for an isolated repeatable case, too
So, I upgraded to IJ2017.2 EAP and Kotlin plugin, as described here: Trouble with EAP - #2 by HughG 1.1.3-eap-34-IJ2017.2-1. That didn’t make my situation any better, so I cut it down to the following test case. I freely admit that I don’t really know what I’m doing in terms of using coroutines to implement async/await, I’m just copying others’ code, as follows.
package org.tameter.ksandbox
import kotlin.browser.window
import kotlin.coroutines.experimental.*
import kotlin.js.Promise
// From https://youtrack.jetbrains.com/issue/KT-17067
private object JavaScriptContext : AbstractCoroutineContextElement(ContinuationInterceptor.Key), ContinuationInterceptor {
override fun <T> interceptContinuation(continuation: Continuation<T>) = object : Continuation<T> {
override val context = continuation.context
override fun resume(value: T) {
window.setTimeout({ continuation.resume(value); }, 0)
}
override fun resumeWithException(exception: Throwable) {
window.setTimeout({ continuation.resumeWithException(exception) }, 0)
}
}
}
// Also from https://youtrack.jetbrains.com/issue/KT-17067
fun <T> immediateAsync(c: suspend () -> T) {
c.startCoroutine(object : Continuation<T> {
override fun resume(value: T) { }
override fun resumeWithException(exception: Throwable) { throw exception }
override val context = JavaScriptContext
})
}
// From https://discuss.kotlinlang.org/t/using-coroutines-to-avoid-callback-hell-when-using-xmlhttprequest/2450/3
fun <T> promiseAsync(c: suspend () -> T): Promise<T> {
return Promise { resolve, reject ->
c.startCoroutine(object : Continuation<T> {
override fun resume(value: T) = resolve(value)
override fun resumeWithException(exception: Throwable) = reject(exception)
override val context = EmptyCoroutineContext
})
}
}
// Also from https://discuss.kotlinlang.org/t/using-coroutines-to-avoid-callback-hell-when-using-xmlhttprequest/2450/3
// Should work with promiseAsync; maybe doesn't make sense to use it with immediateAsync, I'm not sure.
inline suspend fun <T> Promise<T>.await() = suspendCoroutine<T> { c ->
then({
console.log("Resolving with $it")
c.resume(it)
}, {
console.log("Rejecting with $it")
c.resumeWithException(it)
})
}
suspend fun <T> promise(value: T): Promise<T> {
return Promise.resolve(value)
}
fun main(args: Array<String>) {
promiseAsync {
console.log("1")
val a = promise("aardwolf").await()
console.log(a)
console.log("2")
}
}
So, if I run the above code as it stands (in Firefox) I get the following console output.
1 sandbox.js:160:13
Object { } sandbox.js:173:13
2 sandbox.js:174:20
Resolving with aardwolf sandbox.js:113:7
but I was hoping for
1
aardwolf
2
If I have main
call immediateAsync
I get this:
1 sandbox.js:160:13
Object { } sandbox.js:173:13
2 sandbox.js:174:20
Resolving with aardwolf sandbox.js:113:7
TypeError: this$await.then is not a function[Learn More] sandbox.js:125:7
await$lambda/< file:///C:/Users/hughg/Documents/dev/partial-order/web/js/sandbox/sandbox.js:125:7
suspendCoroutine$lambda/< file:///C:/Users/hughg/Documents/dev/partial-order/web/js/sandbox/lib/kotlin.js:29004:7
sandbox</Coroutine$main$lambda.prototype.doResume file:///C:/Users/hughg/Documents/dev/partial-order/web/js/sandbox/sandbox.js:171:29
CoroutineImpl.prototype.doResumeWrapper_0 file:///C:/Users/hughg/Documents/dev/partial-order/web/js/sandbox/lib/kotlin.js:3164:20
CoroutineImpl.prototype.resume_11rb$ file:///C:/Users/hughg/Documents/dev/partial-order/web/js/sandbox/lib/kotlin.js:3153:5
JavaScriptContext$interceptContinuation$ObjectLiteral$resume$lambda/< file:///C:/Users/hughg/Documents/dev/partial-order/web/js/sandbox/sandbox.js:30:7
Am I just doing something dumb here, or missing some simple step?