问题
I am in Clojurescript, and trying to use core.async to get a result from a native Javascript function (I am in the browser), and conditionally integrate it into a map.
I have a function to wrap a native browser call (inspired by Timothy Baldridge's talk on core.async, approx. 34 min for those interested) :
(defn geolocation []
(let [c (chan)
cb (fn [e] (put! c (js->clj e)))]
(if (exists? js/navigator.geolocation)
(.getCurrentPosition js/navigator.geolocation. cb cb)
(put! c {:error "Geolocation is not supported"}))
c))
I can use it like that :
;; this works
(go (.log js/console "RES1 -" (<! (geolocation))))
;; this too (not sure how to print it though)
(go (println "RES2 - " (-> {}
(assoc :test (<! (geolocation))))))
;; this fails... why ?
(go (println "RES3 - " (-> {}
(#(when true
(assoc % :test (<! (geolocation))))))))
The last example fails with an error : Uncaught Error: <! used not in (go ...) block
, even though I thought I was using the same kind of structure.
What am I doing wrong ?
Note : I am requiring it properly from the :require-macro
directive, like described here.
回答1:
The go
macro will take the body it's given and transform all <!
and alt!
and >!
calls to a state machine. However it won't walk into functions:
couldn't use for loop in go block of core.async?
By stops translation at function boundaries, I mean this: the go block takes its body and translates it into a state-machine. Each call to
<!
>!
oralts!
(and a few others) are considered state machine transitions where the execution of the block can pause. At each of those points the machine is turned into a callback and attached to the channel. When this macro reaches a fn form it stops translating. So you can only make calls to<!
from inside a go block, not inside a function inside a code block.This is part of the magic of
core.async
. Without thego
macro, core.async code would look a lot like callback-hell in other langauges.
来源:https://stackoverflow.com/questions/32037795/clojurescript-uncaught-error-used-not-in-go-block