连接ClojureScript bREPL:在编译后的JavaScript中,clojure.browser.repl/connect会抛出TypeError错误。

8
我正在尝试连接到ClojureScript浏览器REPL,但在clojure.browser.repl/connect上遇到了问题。我的编译JavaScript在顶部的Google Closure代码块中抛出TypeError,尝试在null对象上调用appendChild。我正在按照ClojureScript: Up and Running (第9章,第78页,在预览版中提供)中的说明操作,并想知道自那以后是否更改了此工具。我使用Leiningen 2.0.0、Java 1.6.0_37、OS X 10.7.5以及我的project.clj中的依赖项。
(defproject brepl-hello "0.1.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.4.0"]
                 [org.clojure/clojurescript "0.0-1552"]
                 [compojure "1.1.5"]
                 [ring/ring-jetty-adapter "1.1.8"]]
  :plugins [[lein-cljsbuild "0.3.0"]]
  :source-paths ["src/clj"]
  :cljsbuild {:builds [{
                :source-paths ["src/cljs"]
                :compiler {
                 :output-to "resources/public/brepl-hello.js"
                 :optimizations :whitespace 
                 :pretty-print true}}]})

这是唯一的ClojureScript源文件,src/cljs/brepl_hello/brepl-hello.cljs:
(ns brepl-hello
  (:require [clojure.browser.repl :as repl]))

(repl/connect "http://localhost:9000/repl")

这将编译成文件resources/public/brepl-hello.js,我已经将其插入到同一目录下的index.html中:
<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <script type="text/javascript" src="brepl-hello.js"></script>
    </head>
    <body>
    </body>
</html>

我一直在使用Ring/Jetty从REPL或Python SimpleHTTPServer在3000端口提供服务。当我在Chrome中打开此页面时,开发控制台显示 Uncaught TypeError: Cannot call method 'appendChild' of null,并跟踪到编译后的js文件顶部的Google Closure代码中的这个if/else块,在其中传递给包含函数作为参数的parentElmnull
if(goog.userAgent.GECKO || goog.userAgent.WEBKIT) {
    window.setTimeout(goog.bind(function() {
      parentElm.appendChild(iframeElm);
      iframeElm.src = peerUri.toString();
      goog.net.xpc.logger.info("peer iframe created (" + iframeId + ")")
    }, this), 1)
  }else {
    iframeElm.src = peerUri.toString();
    parentElm.appendChild(iframeElm);
    goog.net.xpc.logger.info("peer iframe created (" + iframeId + ")")
  }

这似乎是与 clojure.browser.repl/connect 有关的问题。在ClojureScript源代码中将此行替换为类似以下内容的内容:
(ns brepl-hello
  (:require [clojure.browser.repl :as repl]))

(.write js/document "Hello World!")

可以在浏览器中编译和运行。我怀疑我的构建设置或目录结构配置有误,或者我在所有这些内容中犯了一些新手错误。自从我遵循的指令发布以来发生了什么变化?我在 #clojure irc 日志中找到了几个与此问题相关的参考资料,但没有解决方案。

最后,以下是一个简略的目录树供参考:

├── out
│   ├── cljs
│   │   ├── core.cljs
│   │   └── core.js
│   ├── clojure
│   │   └── browser
│   │       ├── event.cljs
│   │       ├── event.js
│   │       ├── net.cljs
│   │       ├── net.js
│   │       ├── repl.cljs
│   │       └── repl.js
│   └── goog
│       └── [...] 
├── pom.xml
├── project.clj
├── resources
│   └── public
│       ├── brepl-hello.js
│       └── index.html
├── src
│   ├── clj
│   │   └── brepl_hello
│   │       └── core.clj
│   └── cljs
│       └── brepl_hello
│           └── brepl-hello.cljs
└─── target
     ├── brepl-hello-0.1.0-SNAPSHOT.jar
     ├── classes
     ├── cljsbuild-compiler-0
     │   ├── brepl_hello
     │   │   └── brepl-hello.js
     │   ├── cljs
     │   │   ├── core.cljs
     │   │   └── core.js
     │   └── clojure
     │       └── browser
     │           ├── event.cljs
     │           ├── event.js
     │           ├── net.cljs
     │           ├── net.js
     │           ├── repl.cljs
     │           └── repl.js
     └── stale
         └── extract-native.dependencies
2个回答

6

这是一个开源项目,通过查看代码发现在添加repl隐藏iframe时,document.body为空(connect调用导致了此问题)。

你应该在dom准备好或者body加载完成后调用connect方法,这样就可以正常工作了。


你是对的!这是一个普通的未初始化元素。哎呀。 - ecmendenhall

2

很棒的资源,感谢您将它们整理在一起。 - ppbitb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接