gpt4 book ai didi

http - 如何按照异步 channel 在列表中存在的顺序映射异步 channel 列表?

转载 作者:可可西里 更新时间:2023-11-01 16:28:05 26 4
gpt4 key购买 nike

我无法按照创建顺序(与返回值的顺序相反)从浏览器中的 core.async channel 返回值。 channel 本身是从映射 cljs-http.client/get 的 URL 列表返回的。

如果我在 let 中手动绑定(bind)结果 block 然后我可以“手动”按 channel 的顺序返回结果,但是当我不知道有多少个 channel 存在时,这显然是一个问题。

(let [response-channels (map #(http/get "http://date.jsontest.com" {:with-credentials? false}) (range 3))]

; Response is now three channels generated by http/get:

;(#object[cljs.core.async.impl.channels.ManyToManyChannel]
; #object[cljs.core.async.impl.channels.ManyToManyChannel]
; #object[cljs.core.async.impl.channels.ManyToManyChannel])

; If I want the results back in the guaranteed order that I made them, I can do this:
(go (let [response1 (<! (nth response-channels 0))
response2 (<! (nth response-channels 1))
response3 (<! (nth response-channels 2))]
(println "This works as expected:" response1 response2 response3))))

但如果我尝试映射 <!通过 channel 而不是单独绑定(bind)到它们,然后我只得到一个 channel 列表而不是它们的值。

(let [response-channels (map #(http/get "http://date.jsontest.com" {:with-credentials? false}) (range 3))]


(let [responses (into [] (map (fn [c] (go (<! c))) response-channels))]
(println "This just returns the channels:" responses)

; This is still just a vec of many-to-many channels
; [#object[cljs.core.async.impl.channels.ManyToManyChannel]
; #object[cljs.core.async.impl.channels.ManyToManyChannel]
; #object[cljs.core.async.impl.channels.ManyToManyChannel]]
)
)

我怀疑 go 的位置有问题 block ,但是我不能将它移出匿名函数而不会出现错误,我正在使用 <!go 之外 block 。

这行不通:

(into [] (go (map <! response-channels)))

这也不是:

(go (let [responses (into [] (map <! response-channels))]))

我还尝试通过 async/merge 合并 channel 然后使用 async/reduce合并值,但结果按请求完成的时间顺序排列,而不是合并 channel 的顺序。

谁能阐明如何按照 channel 在列表中存在的顺序从 channel 列表中检索值?

最佳答案

在 Clojure 中你可以做 (map <!! response-channels) ,但这在 ClojureScript 中是不可能的。更重要的是,不鼓励使用map。 — 或一般的惰性操作 — 用于副作用(查看 this blog post 了解原因)。您的代码没有产生您期望的结果的原因是(嵌套)使用 fngo 内 block (参见 this answer ):

By [the Clojure go-block] stops translation at function boundaries, I mean this: the go block takes its body and translates it into a state-machine. Each call to <! >! or alts! (and a few others) are considered state machine transitions where the execution of the block can pause. At each of those points the machine is turned into a callback and attached to the channel. When this macro reaches a fn form it stops translating. So you can only make calls to <! from inside a go block, not inside a function inside a code block.

我不太确定,但是当你看一下 (source map) 时你会看到它调用了 fn直接以及通过其他功能(例如 lazy-seq ),这可能就是为什么 (go (map <! response-channels)) 的原因不起作用。

无论如何,doseq怎么样? :

(go (doseq [c response-channels]
(println (<! c))))

这将遵守 response-channels 内的顺序.

关于http - 如何按照异步 channel 在列表中存在的顺序映射异步 channel 列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37989606/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com