如何延迟我们发送到通道的元素



假设我们有一个类似的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符合您的标准,因为它应该立即返回一个关于值是否发布的结果。

这里,send()暂停,直到可能的延迟结束。如果你不想等待,你就必须在每次发送东西时启动一个协同程序。

由于频道";构造函数";不是一个真正的构造函数,你不能将其子类化。我的解决方法是创建一个将其用作委托的类。

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)
}
}

最新更新