Concurrency 等待一系列承诺?
我有一连串的承诺。我想等到它们都可用后,再去求整个向量 我的实际用例是生成多个并发请求,然后在所有请求都返回后处理它们 集合的排序很重要,但可能会伪造,并在事件发生后重新排序 我目前正在做这样的事情:Concurrency 等待一系列承诺?,concurrency,clojure,promise,core.async,Concurrency,Clojure,Promise,Core.async,我有一连串的承诺。我想等到它们都可用后,再去求整个向量 我的实际用例是生成多个并发请求,然后在所有请求都返回后处理它们 集合的排序很重要,但可能会伪造,并在事件发生后重新排序 我目前正在做这样的事情: (defn parallel-api-query [queries] (let [qs (map http/get queries) bodies (map #(json/read-str (:body @%)) qs)] bodies)) 所有查询都在qs绑定中
(defn parallel-api-query
[queries]
(let [qs (map http/get queries)
bodies (map #(json/read-str (:body @%)) qs)]
bodies))
所有查询都在qs
绑定中发出,然后映射将依次在每个查询上阻塞,直到其在map
中被解除
这会达到我想要的结果吗?这个实现一开始可能会奏效,特别是如果您通过传入一个查询URL向量来单独测试函数,这是因为Clojure使用了
map
函数以及它们是如何处理的。但是,您不应该依赖于这种行为,因为如果调用代码开始传入一些非分块序列(例如列表,或另一个由谁知道是什么输入计算的惰性序列),您将失去并行性
请记住,map
是惰性的,因此将qs
绑定为(映射http/get查询)
将产生一个惰性序列,该序列在强制提交请求之前不会提交请求。这个错误由于以下事实而变得更加复杂:(map#(json/read str(:body@%)qs)
返回另一个惰性序列,该序列将处理(惰性)qs
序列,提交API调用,然后在函数调用方从返回序列请求项时一次阻塞一个API调用。在最坏的情况下,API请求将按顺序提交
为了确保所有请求都是并行提交的,并且所有响应都已收到,请将对
map
(请求和deref)的调用封装在doall
中,这将强制评估延迟序列。看起来合理,您试过运行它吗?我以前使用过这种技术,应该行得通。但是请注意,每个查询的处理都会被阻塞,等待前面的任何较慢的查询,因此结果的处理有点“急促”(100%非并行)。@Alan Thompson我假设由于序列分块,他最多会收到32个并发请求。即使“分块”,它仍然是顺序的。“@”deref将为每个将来阻塞线程,直到它完成。seq中已经完成的后续期货将在所有上游期货之前无法处理。谢谢大家。是的,我试过运行它,我只是想确保我没有错过一个我不知道的语言功能。谢谢。我编辑了你的答案,以强调这两张地图都需要DOALING。