关!没有取消订阅的订阅频道
close! a subscription channel without unsub
在没有先使用 unsub
的情况下在订阅频道上使用 close!
有什么影响?
这会产生隐含的 unsub
+ a close!
的效果还是会产生任何不需要的副作用?
我无法从文档中确定答案,所以我做了一个小的异步实验来确定没有 unsub
的 close!
是否安全。
(ns pubsub.experiment
(:require [clojure.core.async :as >]))
(def publisher (>/chan))
(def p (>/pub publisher (constantly nil)))
(def answers (>/chan))
(defn consume
[label count]
(let [s (>/sub p nil (>/chan))]
(>/go-loop [i 0]
(if (> i count)
(>/close! s)
(do
(>/>! answers [label (>/<! s)])
(recur (inc i)))))))
(defn -main
[& args]
(println "running pubsub experiment")
(consume :a 1)
(consume :b 2)
(consume :c 3)
(consume :d 4)
(consume :e 5)
(>/go-loop []
(println "result: " (>/<! answers))
(recur))
(>/<!! (>/onto-chan publisher (range 10)))
(System/exit 0))
然后 运行 它(bench.jar 是一个包含 clojure 加上 core.async 和其他几个库的 uberjar)。
$ java -cp ~/bin/bench.jar:. clojure.main -m pubsub.experiment
running pubsub experiment
result: [:a 0]
result: [:b 0]
result: [:c 0]
result: [:d 0]
result: [:e 0]
result: [:a 1]
result: [:b 1]
result: [:c 1]
result: [:d 1]
result: [:e 1]
result: [:b 2]
result: [:c 2]
result: [:d 2]
result: [:e 2]
result: [:c 3]
result: [:d 3]
result: [:e 3]
result: [:d 4]
result: [:e 4]
result: [:e 5]
$
正如我们所见,close!
调用不会干扰任何其他订阅的频道,并且每个频道在关闭前都会看到我们预期的所有结果。
pub
和 sub
是根据 mult
:
实现的
发布频道的每个主题对应于注册该主题的第一个订阅时创建的 mult,
每个 sub
调用都会在与相关主题对应的 mult 上对 tap
进行 under-the-hood 调用。
Mults 在内部设置为移除最终进入关闭通道的 tap(这在 mult
的文档字符串中有记录)。在订阅的上下文中,这意味着如果订阅频道关闭,则在该主题的消息第一次发布到发布频道时,它的点击将从它的 mult 中删除,或者换句话说,close!
导致隐式 unsub
.
请注意,unsub
和 close!
都不会导致主题本身(以及相应的 mult)从出版物的注册中删除。如果您希望发生这种情况,可以使用 unsub-all
.
在没有先使用 unsub
的情况下在订阅频道上使用 close!
有什么影响?
这会产生隐含的 unsub
+ a close!
的效果还是会产生任何不需要的副作用?
我无法从文档中确定答案,所以我做了一个小的异步实验来确定没有 unsub
的 close!
是否安全。
(ns pubsub.experiment
(:require [clojure.core.async :as >]))
(def publisher (>/chan))
(def p (>/pub publisher (constantly nil)))
(def answers (>/chan))
(defn consume
[label count]
(let [s (>/sub p nil (>/chan))]
(>/go-loop [i 0]
(if (> i count)
(>/close! s)
(do
(>/>! answers [label (>/<! s)])
(recur (inc i)))))))
(defn -main
[& args]
(println "running pubsub experiment")
(consume :a 1)
(consume :b 2)
(consume :c 3)
(consume :d 4)
(consume :e 5)
(>/go-loop []
(println "result: " (>/<! answers))
(recur))
(>/<!! (>/onto-chan publisher (range 10)))
(System/exit 0))
然后 运行 它(bench.jar 是一个包含 clojure 加上 core.async 和其他几个库的 uberjar)。
$ java -cp ~/bin/bench.jar:. clojure.main -m pubsub.experiment
running pubsub experiment
result: [:a 0]
result: [:b 0]
result: [:c 0]
result: [:d 0]
result: [:e 0]
result: [:a 1]
result: [:b 1]
result: [:c 1]
result: [:d 1]
result: [:e 1]
result: [:b 2]
result: [:c 2]
result: [:d 2]
result: [:e 2]
result: [:c 3]
result: [:d 3]
result: [:e 3]
result: [:d 4]
result: [:e 4]
result: [:e 5]
$
正如我们所见,close!
调用不会干扰任何其他订阅的频道,并且每个频道在关闭前都会看到我们预期的所有结果。
pub
和 sub
是根据 mult
:
发布频道的每个主题对应于注册该主题的第一个订阅时创建的 mult,
每个
sub
调用都会在与相关主题对应的 mult 上对tap
进行 under-the-hood 调用。
Mults 在内部设置为移除最终进入关闭通道的 tap(这在 mult
的文档字符串中有记录)。在订阅的上下文中,这意味着如果订阅频道关闭,则在该主题的消息第一次发布到发布频道时,它的点击将从它的 mult 中删除,或者换句话说,close!
导致隐式 unsub
.
请注意,unsub
和 close!
都不会导致主题本身(以及相应的 mult)从出版物的注册中删除。如果您希望发生这种情况,可以使用 unsub-all
.