我有一个通道,我将值放入doseq循环中。
此代码从isbns列表中读取,并且对于每个isbn,执行亚马逊搜索以返回书籍的内容,然后调用另一个函数来获取标题和等级
(def book_channel (chan 10))
答案 0 :(得分:2)
确保使用clojure.core.async/into
而不是clojure.core/into
。这是一个从收集到通道再回到收集的往返旅程的例子:
user> (require '[clojure.core.async :as async :refer [<! <!! >!! >! chan go]])
nil
user> (def book-chan (async/to-chan [:book1 :book2 :book3]))
#'user/book-chan
user> (<!! (clojure.core.async/into [] book-chan))
[:book1 :book2 :book3]
clojure.core.async/into
会返回一个通道,该通道只会写入一个项目。一旦输入通道关闭,就会写入一个项目。这使整个事物保持异步,并且它确实要求将内容放入书籍频道的代码关闭陈以表明所有书籍都在那里。
答案 1 :(得分:1)
你应该关闭!完成推送内容之后的book_channel。每个async / into文档 - “ch必须在生成结果之前关闭。”
(let [book> (chan)]
(go
(doseq [e (range 8)]
(>! book> e))
(close! book>))
(<!! (async/into [] book>)))
或者,你可以使用async / to-chan来为你关闭频道:
(let [book> (chan)]
(async/onto-chan book> (range 8))
(<!! (async/into [] book>)))
答案 2 :(得分:1)
您需要进行某种类型的协调,以确定您的所有工作何时完成。您可以非常轻松地将协调分配到主线程中:
(def book_channel (chan 10))
(defn concurrency_test
[list_of_isbns]
(doseq [isbn list_of_isbns]
(go (>! book_channel
(get_title_and_rank_for_one_isbn
(amazon_search isbn)))))
(prn (loop [results []]
(if (= (count results) (count list_of_isbns))
results
(recur (conj results (<!! book_channel)))))))
在这里,我使用了一个循环,它一直等待结果并将它们添加到向量中,直到我们得到与isbns一样多的结果。您希望确保get_title_and_rank_for_one_isbn
始终生成可以放在频道上的结果,否则循环将永远等待。