我必须在这里遗漏一些非常明显的东西,但我正在尝试设置一个非常基本的程序,将一个项目放到一个通道上,然后阻止,直到我再次取消它。整个计划如下:
(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
在我忘记之前我有这个错误:引用chan(如果我只是打开频道,然后再关闭它,程序运行正常)
但是,当我想使用<!!
或>!!
宏时,此代码似乎会窒息。
答案 0 :(得分:34)
clojurescript中的core.async的clojurecript有什么不同。
因为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")))
在并发线程版本中,您将看到即使是首先运行的代码也是读取,它实际上是另一个例程,因此稍后运行的代码(>!
)有效地运行解锁第一个例程。 / p>
您可以将go
宏视为产生一个最终将同时开始执行的新线程,并将控制权立即返回到下一个代码指令。
我建议阅读code walk-through忽略特定部分(>!! <!!
等)和一些很棒的swannodette's tutorials(如Clojurescript 101和Communicating Sequential Processes)
答案 1 :(得分:3)
core.async的ClojureScript版本不包含<!!
或>!!
。
除了实际来源之外,我无法找到此消息来源:https://github.com/clojure/core.async/blob/56ded53243e1ef32aec71715b1bfb2b85fdbdb6e/src/main/clojure/cljs/core/async.cljs