请分享您的想法在 2024 年 Clojure 状态调查!

欢迎!请查看 关于 页面了解更多关于这是如何工作的信息。

0
ClojureScript
{code:title=mylib.js}
mylib = { abc: 3 }


{code:title=co.edn}
{:foreign-libs [{:file "mylib.js"
                 :provides ["my-lib"]
                 :global-exports {my-lib mylib}}]}


重现


$ clj -m cljs.main -co co.edn -r
ClojureScript 1.10.339
cljs.user=> (require 'my-lib')

cljs.user=> my-lib/abc
TypeError: Cannot read property 'abc' of undefined
     (<NO_SOURCE_FILE>)
cljs.user=> (require 'my-lib')

cljs.user=> my-lib/abc
3


这不在 Node 和 Nashorn REPLs 中出现。

7 答案

0

评论者:mfikes

问题是浏览器 require 是异步的(至少在 REPL 中),因此设置全局导出的代码与加载 require 代码会竞争。

CLJS-2854-0.patch 探索了解决这个问题的一种方法(还没有包括测试等),通过在浏览器 REPL 中条件性地队列代码,然后在加载队列清空后执行。

0

评论者:mfikes

CLJS-2854-1.patch 引入了一个机制,允许 REPL 说明它们是否有队列后加载活动的方式,并且浏览器 REPL 参与了这个机制。使用的名称可以进行清理,特别是如果这导致了公共 API,REPL 可以使用。

0
作者

评论者:mfikes

使用以下代码

`
(ns foo.core
(:require my-lib))

(def x my-lib/abc)
`

补丁应用后一切正常

`
$ clj -m cljs.main -co co.edn -r
cljs.user=> (require 'foo.core)

cljs.user=> foo.core/x
3
`

0
作者

评论者:dnolen

为了稍微澄清问题——REPL中的require形式自动位于cljs.user中,这意味着直接导入具有全局导出的库会进行竞态,因为该库的出口映射紧跟在该库的goog.require之后,但是将是异步加载,所以这不会工作。这不会影响传递性情况。

0
作者

评论者:mfikes

CLJS-2854-2.patch尝试通过使用超时来避免竞态,来保持编译器代码中的逻辑。

0
作者

评论者:mfikes

CLJS-2854-2.patch不再适用。

0
作者
参考:[https://clojure.atlassian.net/browse/CLJS-2854](https://clojure.atlassian.net/browse/CLJS-2854)(由mfikes报告)
...