2024Clojure状态调查! 中分享您的想法。

欢迎!有关此功能的更多信息,请查看 关于 页面。

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 REPL 中不会发生此问题。

7 答案

0
by

评论者:mfikes

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

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

0
by

评论者:mfikes

CLJS-2854-1.patch 引入了一种机制,允许 REPL 标识它们是否有排队后加载活动的功能,并且让浏览器 REPL 参与此机制。使用的名称可以清理,特别是如果这导致了可以由 REPLs 使用的公共 API。

0
by

评论者: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
by

评论者:dnolen

为了更清楚地说明问题,问题是REPL中的{{(require ...)}}形式在隐式地位于{{cljs.user}},这意味着对具有全局导出库的直接导入将会发生竞争,因为该库的导出映射紧随库的{{goog.require}}之后,但那将是一个异步加载,所以它不会工作。这不会影响间接情况。

0
by

评论者:mfikes

CLJS-2854-2.patch试图通过简单地使用超时来避免竞争的方式来保持编译器代码中的逻辑。

0
by

评论者:mfikes

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

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