Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure Core.async:从承诺通道集合中获取所有值_Clojure_Core.async - Fatal编程技术网

Clojure Core.async:从承诺通道集合中获取所有值

Clojure Core.async:从承诺通道集合中获取所有值,clojure,core.async,Clojure,Core.async,考虑这样一个数据集: (def data [{:url "http://www.url1.com" :type :a} {:url "http://www.url2.com" :type :a} {:url "http://www.url3.com" :type :a} {:url "http://www.url4.com" :type :b}]) ;; (go (put! result-c (concat (<! (nt

考虑这样一个数据集:

(def data [{:url "http://www.url1.com" :type :a}
           {:url "http://www.url2.com" :type :a}
           {:url "http://www.url3.com" :type :a}
           {:url "http://www.url4.com" :type :b}])
;; (go (put! result-c (concat (<! (nth chans 0))
;;                            (<! (nth chans 1))
;;                            (<! (nth chans 2))
;;                            (<! (nth chans 3)))))
;; instead of above, now you can do this:
(->> chans
     async/merge
     (async/reduce into []))
应该同时请求这些URL的内容。根据项的:type值,这些内容应该由相应的函数解析。一旦所有响应到达,解析函数将返回集合,这些集合应该连接起来

因此,让我们假设有函数
parse-a
parse-b
,当传递一个包含
HTML
内容的字符串时,这两个函数都返回一个字符串集合

看起来
core.async
可能是一个很好的工具。每个项目可以有单独的通道,也可以只有一个通道。我不确定这里哪条路更合适。对于多个通道,可以使用传感器进行后处理/解析。还有一个特殊的
promise chan
,在这里可能是合适的

这是一个代码草图,我正在使用一个基于回调的
HTTP工具包
函数。不幸的是,我在go块中找不到通用的解决方案

(defn f [data] 
  (let [chans (map (fn [{:keys [url type]}] 
                     (let [c (promise-chan (map ({:a parse-a :b parse-b} type)))] 
                       (http/get url {} #(put! c %))
                       c))
                   data)
        result-c (promise-chan)] 
    (go (put! result-c (concat (<! (nth chans 0))
                               (<! (nth chans 1))
                               (<! (nth chans 2))
                               (<! (nth chans 3)))))
    result-c))
(定义f[数据]
(let[chans(map(fn[{:keys[url-type]}]
(让[c(promise chan(map({:a parse-a:b parse-b}类型)))]
(http/geturl{}#(put!c%))
c) )
(数据)
结果-c(陈国荣)]
(去(放)!结果-c(混凝土)(
结果可以这样解读:

(go (prn (<! (f data))))

(go(prn(我认为
promise chan
在这里弊大于利。问题是大部分
core.async
API(
a/merge
a/reduce
等))依赖于这样一个事实,即通道将在某个点关闭,
promise chan
反过来永远不会关闭

因此,如果坚持使用
core.async
对您来说至关重要,那么更好的解决方案将不是使用
promise chan
,而是使用普通通道,在第一次
put!
后关闭该通道:

...
(let [c (chan 1 (map ({:a parse-a :b parse-b} type)))]
  (http/get url {} #(do (put! c %) (close! c)))
  c)
...
此时,您使用的是封闭通道,事情变得更简单。要收集所有值,您可以执行以下操作:

(def data [{:url "http://www.url1.com" :type :a}
           {:url "http://www.url2.com" :type :a}
           {:url "http://www.url3.com" :type :a}
           {:url "http://www.url4.com" :type :b}])
;; (go (put! result-c (concat (<! (nth chans 0))
;;                            (<! (nth chans 1))
;;                            (<! (nth chans 2))
;;                            (<! (nth chans 3)))))
;; instead of above, now you can do this:
(->> chans
     async/merge
     (async/reduce into []))
(go)(put)(put)result-c(concat)(chans) 异步/合并 (异步/还原为[])
UPD(以下是我个人的看法):

似乎,使用
core.async
通道作为承诺(无论是以
promise chan
的形式,还是在单个
put!
之后关闭的通道)并不是最好的方法。随着事情的发展,原来
core.async
API总体上是(您可能已经注意到)虽然不是那么令人愉快。还有一些可能会迫使您编写更少的惯用代码。此外,没有内置的错误处理(如果错误发生在
go
-block中,
go
-block将静默返回
nil
)为了解决这个问题,你需要拿出你自己的东西(重新发明轮子)因此,如果您需要承诺,我建议您为此使用特定的库,例如或。

async.core
中使用以同步启动异步操作,如
http/get
,同时以与输入相同的顺序交付结果:

(let [result (chan)] 
  (pipeline-async 
    20 result
    (fn [{:keys [url type]} ch]
      (let [parse ({:a parse-a :b parse-b} type)
            callback #(put! ch (parse %)(partial close! ch))]  
        (http/get url {} callback)))
    (to-chan data))
  result)

我也想要这个功能,因为我真的很喜欢
core.async
,但我也想在某些地方使用它,比如传统的
JavaScript
承诺。我想出了一个使用宏的解决方案。在下面的代码中,
如果有人还在看这个问题,可以通过@OlegTheCat补充答案:

对于错误,可以使用单独的通道

(:require [cljs.core.async :as async]
            [cljs-http.client :as http])
(:require-macros [cljs.core.async.macros :refer [go]])

(go (as-> [(http/post <url1> <params1>)
           (http/post <url2> <params2>)
           ...]
          chans
          (async/merge chans (count chans))
          (async/reduce conj [] chans)
          (async/<! chans)
          (<callback> chans)))
(:require[cljs.core.async:as async]
[cljs-http.client:作为http])
(:需要宏[cljs.core.async.macros:refere[go]])
(go(as->[(http/post)
(http/post)
...]
chans
(异步/合并通道(计数通道))
(异步/减少连接[]通道)
(异步/通道)

您的具体问题是什么?实际上,在此期间,我或多或少地想到了您提出的解决方案。在我决定将错误处理添加到解决方案中之前,该解决方案工作得很顺利。我可能会使用简单的承诺。