node.js - 如何耗尽 channel 的值然后返回结果(ClojureScript)?

标签 node.js clojure clojurescript

假设 channel chan 在队列中有值“1”和“2”。

目标:创建一个接受chan 并返回向量[1 2] 的函数。请注意,如果此函数在返回其值之前必须阻塞一段时间,我完全没问题

尝试:

(defn chan->vector
  [chan]  
  (let [a (atom true) v []]
    (while (not-nil? @a)
      (go
        (reset! a (<! chan))
        (into v @a)
        (reset! a (<! chan))
      )
    ) v
  )
)

结果: 我的 REPL 卡住并最终吐出一个巨大的错误。我开始意识到这是因为 (go ...) block 是异步的,所以会立即返回。因此,我的 (while ...) 循环中的原子永远不会有机会被设置为 nil 并且循环永远不会终止。

那么如何才能达到预期的效果呢?如果相关,我正在使用 ClojureScript 并以 nodejs 为目标。

最佳答案

你应该使用alts!来自 core.async完成这个任务 ( https://clojure.github.io/core.async/#clojure.core.async/alts !):

(def x (chan 10))

(go (>! x 1)
    (>! x 2)
    (>! x 3))

(defn read-all [from-chan]
  (<!! (go-loop [res []]
           (let [[v _] (alts! [from-chan] :default :complete)]
             (if (= v :complete)
               res
               (recur (conj res v)))))))

(read-all x) 
;; output: [1 2 3]

(read-all x)
;; output: []

(go (>! x 10)
    (>! x 20)
    (>! x 30)
    (>! x 40))

(read-all x)
;; output: [10 20 30 40]

go-loop里面这个(a/alts! [from-chan] :default :complete)尝试从 channel 读取任何值,如果立即没有可用值,它会发出默认值,因此您会看到您应该打破循环并返回累积值。

更新:由于cljs中没有blocking read ( <!! ),你可以重写如下:

(defn read-all [from-chan]
  (go-loop [res []]
    (let [[v _] (alts! [from-chan] :default :complete)]
      (if (= v :complete)
        res
        (recur (conj res v)))))))

所以它将返回 channel ,然后只从那里读取一个值:

(go (let [res (<! (read-all x))]
      (println res)
      ;; do something else
      ))

关于node.js - 如何耗尽 channel 的值然后返回结果(ClojureScript)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34560423/

相关文章:

javascript - 在node.js应用程序中, mdkirSync ('mydir' ,700) 导致权限 d-w------T

json - 在 Clojurescript 中处理突变

clojurescript - 试剂组件未更新

clojure - 在clojure中对一系列 bool 值进行分组?

Clojure:检查两个原子中具有相同键的值是否相等(使用 add-watch)

javascript - Next.js 和 Webpack 内联 Javascript 或 CSS 资源

javascript - node.js 正则表达式字符串参数中的匹配组不起作用

node.js - 使用 pdsh 远程运行 node.js pm2

recursion - 不在尾部位置重复

clojure - 将多个谓词函数组合为一个