如何创建一个可以多次调用的函数从非暂停上下文并且在自第一次调用以来的特定延迟之后,可暂停函数运行?
我试图在 Kotlin 中重新创建的 Javascript 代码:
const DELAY_MS = 500
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
const schedulable = () => console.log('schedulable function is running')
let timeout = null
const schedule = () => {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null
schedulable()
}, DELAY_MS)
}
}
;(async () => {
schedule()
await sleep(100)
schedule()
schedule()
await sleep(200)
schedule()
})()
// result: 'schedulable function is running' is printed once
Kotlin 尝试(似乎可行,但使用了 GlobalScope):
object SchedulableAttempt {
private fun schedulable() {
println("schedulable function is running")
}
private const val DELAY_MS = 500L
private var deferred: Deferred<Unit>? = null
fun schedule() {
if(deferred === null){
synchronized(this){
deferred = GlobalScope.async {
delay(DELAY_MS)
deferred = null
schedulable()
}
}
}
}
}
fun main() {
thread {
SchedulableAttempt.schedule()
Thread.sleep(100)
SchedulableAttempt.schedule()
SchedulableAttempt.schedule()
Thread.sleep(200)
SchedulableAttempt.schedule()
}
runBlocking { // just to keep the app running
delay(1000)
}
}
如何在 Kotlin 中正确执行此操作?这样的解决方案有什么陷阱吗? Kotlin 文档明确表示要避免在非顶级协程的情况下使用 GlobalScope,因为它会造成内存泄漏