等待 collection 个承诺?

Waiting on a collection of promises?

我有一系列的承诺。我想等到它们都可用,然后取消引用以获取整个向量。

我的实际用例是 using HTTPKit 发出多个并发请求,然后在所有请求都返回时处理它们。

collection 的顺序很重要,但可以在事件发生后伪造 re-ordered。

我目前正在做这样的事情:

(defn parallel-api-query
  [queries]
  (let [qs (map http/get queries)
        bodies (map #(json/read-str (:body @%)) qs)]
    bodies))

所有查询都在 qs 绑定中发出,然后地图将依次阻塞每个查询,直到它在 map 中取消引用。

这样会达到我想要的结果吗?

由于 Clojure 对 chunked sequences 的使用以及它们的处理方式,此实现一开始可能看起来有效,特别是如果您通过传入查询 URL 向量来单独测试函数map 函数。但是,您不应该依赖这种行为,因为如果调用代码开始传递一些非分块序列(例如列表,或者根据谁知道什么输入计算的另一个惰性序列),您将失去并行性。

请记住 map 是惰性的,因此将 qs 绑定为 (map http/get queries) 将产生一个 lazy 序列,该序列不会提交请求,直到它被迫这样做。 (map #(json/read-str (:body @%)) qs) returns 另一个惰性序列将处理(惰性)qs 序列,提交 API 调用,然后一次阻塞它们函数的调用者从返回的序列中请求项目的时间。在最坏的情况下,您的 API 请求将按顺序提交。

为确保您的所有请求都是并行提交的,并且所有响应都已收到,请将对 map 的调用(包括请求和取消引用)包装在 doall 中,这将强制计算惰性序列。