如何延迟我们发送到 Channel 的元素?

How to delay the elements the we send to a Channel?

假设我们有这样一个Channel

private val channel = Channel<String>(1)

我们正在收听像这样的 Channel 个元素

channel.receiveAsFlow().collect { myStr ->
    println(myStr)
}

如果我运行像这样

private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
...
fun sendMessage(myMessage: String) {
   scope.launch {
      channel.send(myMessage)
   }
}
...
sendMessage("a")
sendMessage("b")
sendMessage("c")
sendMessage("d")

输出将是

a
b
c
d

现在,我想要实现的是,如果我发送 "b" 它会延迟通道中元素的处理 1 秒。

例如,如果我这样做

...
sendMessage("a")
sendMessage("b")
sendMessage("c")
sendMessage("b")
sendMessage("d")
sendMessage("e")

我期望的输出是这样的

a // prints immediately
b // prints right after a
c // prints after 1 second
b // prints right after c
d // prints after 1 second
e // prints right after d

我的问题是,我将如何实现这种行为?我一直在尝试在这里和那里添加 delay(),但我没有任何运气。

这是一个想法,但我觉得有点老套。 trySend 不适用于此。我不确定如何使 trySend 符合您的标准,因为它应该 return 立即得出有关值是否已发布的结果。

这里,send()暂停,直到可能的延迟结束。如果您不想等待,则每次发送内容时都必须启动协程。

由于 Channel“构造函数”不是真正的构造函数,您不能将其子class。我的解决方法是创建一个将其用作委托的 class。

val backingChannel = Channel<String>(1)
val channel = object: Channel<String> by backingChannel {
    var delayNext = false
    val mutex = Mutex()
    override suspend fun send(element: String) = mutex.withLock {
        if (delayNext) {
            delay(1000)
        }
        delayNext = element == "b"
        backingChannel.send(element)
    }
}