我一定在这里遗漏了一些非常明显的东西,但我正在尝试设置一个非常基本的程序,将一个项目放到一个 channel 上,然后阻止,直到我可以再次取下它。整个程序如下:
(ns shopping-2.core
(:require [cljs.core.async :as async :refer [>!! <!! put! chan <! close! <!!]]))
(let [c (chan)]
(>!! c "hello")
(.write js/document (<!! c))
(close! c))
我得到的 JavaScript 错误是:
Uncaught TypeError: Cannot call method 'call' of undefined
我之前有过那个错误,当我忘记 :refer chan in (如果我只是打开 channel ,然后再次关闭它,程序运行良好)
但是,当我想使用
<!!
时,此代码似乎会窒息或 >!!
宏。
最佳答案
clojurescript 中的可用内容与 core.async 的 clojure 版本存在一些差异。
由于 JVM 上的 clojure 具有真实线程,因此它可以使用真实线程和 go 块的并发模式:
thread
包含 core.async 魔法它的并发宏和函数以两个刘海结尾,比如
<!!
, >!!
, alt!!
和 alts!!
. (假线程)使用
go
包含 core.async 魔法的宏并使用最后一个爆炸的功能,如
<!
, >!
,alt!
和 alts!
. 在 clojurescript(在 js 中运行)中没有真正的线程,因此只有 IoC(控制反转)线程可用,这意味着您必须使用并发构造的第二种变体。
你的例子是这样的:
(ns shopping-2.core
(:require-macros [cljs.core.async.macros :refer [go]])
(:require [cljs.core.async :as async :refer [put! chan <! >! close!]]))
(go
(let [c (chan)]
(>! c "hello")
(.write js/document (<! c))
(close! c)))
无论如何,该示例存在并发问题,因为
<! >!
函数正在阻塞并且您在同一个例程中放入 chan,该例程将在 (>! c "hello")
上阻塞指令,它永远不会读,肯定会饿死你的程序。您可以使用
put!
解决此问题fn 没有阻塞,或者在不同的例程中有效地运行这些指令,我认为这更好地展示了你打算做什么。(ns shopping-2.core
(:require-macros [cljs.core.async.macros :refer [go]])
(:require [cljs.core.async :as async :refer [put! chan <! >! close!]]))
;; put! version
(go
(let [c (chan)]
(put! c "hello")
(.write js/document (<! c))
(close! c)))
;; Concurrent version
;; 2 *threads* concurrently running. One is the putter and the other is the
;; reader
(let [c (chan)]
(go
(.write js/document (<! c))
(close! c))
(go
(>! c "hello")))
在并发线程版本中,您会看到即使首先运行的代码也是读取,它实际上是另一个例程,因此稍后运行的代码(
>!
)有效地运行,从而解除了第一个例程的阻塞。你可以想到
go
宏生成一个新线程,该线程最终将开始并发执行,并立即将控制权返回到下一条代码指令。我建议阅读 code walk-through忽略 clojure 特定部分(
>!! <!!
等)和一些 swannodette's tutorials哪些很棒(比如 Clojurescript 101 和 Communicating Sequential Processes)
关于clojure - 似乎不需要>!!或 <!!在 Clojurescript 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21400464/