Clojurescript - Uncaught Error: <! used not in (go …) block

*爱你&永不变心* 提交于 2019-12-11 09:15:25

问题


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 <! >! or alts! (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 the go 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!