【问题标题】:Clojurescript - Uncaught Error: <! used not in (go ...) blockClojurescript - 未捕获的错误:<!不在 (go ...) 块中使用
【发布时间】:2015-08-16 17:09:55
【问题描述】:

我在 Clojurescript 中,并尝试使用 core.async 从原生 Javascript 函数(我在浏览器中)获取结果,并有条件地将其集成到地图中。

我有一个封装原生浏览器调用的函数(受Timothy Baldridge's talk on core.async 启发,感兴趣的人大约需要 34 分钟):

(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))

我可以这样使用它:

   ;; 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))))))))

最后一个示例失败并出现错误:Uncaught Error: &lt;! used not in (go ...) block,尽管我认为我使用的是相同类型的结构。

我做错了什么?

注意:我从:require-macro 指令like described here 正确要求它。

【问题讨论】:

    标签: clojurescript core.async


    【解决方案1】:

    go 宏将获取给定的主体,并将所有 &lt;!alt!&gt;! 调用转换为状态机。但是它不会进入函数:

    couldn't use for loop in go block of core.async?

    通过在函数边界处停止转换,我的意思是:go 块获取其主体并将其转换为状态机。对&lt;!&gt;!alts!(以及其他一些)的每次调用都被视为状态机转换,其中块的执行可以暂停。在这些点中的每一个点,机器都会变成回调并附加到通道。当此宏到达 fn 形式时,它会停止翻译。所以你只能从 go 块内部调用&lt;!,而不是代码块内部的函数。

    这是core.async 的魔力的一部分。如果没有 go 宏,core.async 代码在其他语言中看起来很像回调地狱。

    【讨论】:

    • 看起来我在这里经常见到你 :) 再次感谢。也可以编辑你的引文,它在“所以你只能打电话给”之后被剪掉......
    • 另外,如果您有关于如何构建此类代码的指示,我会很高兴。
    • @nha 我一直在考虑这个问题。这可能不是讨论它的正确地方,但它可能有助于认为使用 core.async 时传递的单元是通道 - 如果您需要制作执行异步操作的可重用函数,请返回通道。这样,使用这些函数的代码可以做任何事情,设置 go-loops、go 块和阻塞 puts/takes(!! 运算符,在 clj not in cljs 中可用)。因此,您可以通过返回通道并在 geolocation 函数之外执行 put 来避免 OP 的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 2015-11-22
    • 2018-12-01
    • 1970-01-01
    • 2022-10-25
    • 2022-08-13
    • 2015-12-10
    相关资源
    最近更新 更多