如何在Clojurescript中捕获任何Javascript异常?

28

在我的通信层中,我需要能够捕捉任何JavaScript异常,将其记录下来,并按照正常流程进行处理。

目前在Clojurescript中,捕捉异常的语法规定我必须指定被捕获的异常类型。

我尝试使用 nil、js/Error、js/object 在 catch 表达式中,但无法捕捉到任何 JavaScript 异常(这些异常可能将字符串作为对象类型)。

我希望得到一些提示,如何在 Clojurescript 中本地实现此功能。


嗨 Dima!你觉得我的回复解决了你的问题吗? - tangrammer
3个回答

53

我在David Nolen的"Light Table ClojureScript Tutorial"中找到了另一个可能的答案。

;; Error Handling
;; ============================================================================

;; Error handling in ClojureScript is relatively straightforward and more or
;; less similar to what is offered in JavaScript.

;; You can construct an error like this.

(js/Error. "Oops")

;; You can throw an error like this.

(throw (js/Error. "Oops"))

;; You can catch an error like this.

(try
  (throw (js/Error. "Oops"))
  (catch js/Error e
    e))

;; JavaScript unfortunately allows you to throw anything. You can handle
;; this in ClojureScript with the following.

(try
  (throw (js/Error. "Oops"))
  (catch :default e
    e))

这是现在正确的做法。 - johnbakers
“:default”在“常规”(基于Java的)Clojure中目前不存在,但有一个提案将其添加到其中:http://dev.clojure.org/jira/browse/CLJ-1293 - Hutch Moore
#?(:cljs :default :clj Throwable),在 cljc 文件中使用 :default 可以同时适用于 clj 和 cljs。 - Chris Murphy

6

看起来js/Object能够捕获所有异常(在https://himera.herokuapp.com上测试过):

cljs.user> (try (throw (js/Error. "some error")) (catch js/Object e (str "Caught: " e)))
"Caught: Error: some error"
cljs.user> (try (throw "string error") (catch js/Object e (str "Caught: " e)))
"Caught: string error"
cljs.user> (try (js/eval "throw 'js error';") (catch js/Object e (str "Caught: " e)))
"Caught: js error"

需要注意的一件事是惰性序列。如果在惰性序列中抛出错误,那么直到退出try函数后,该代码部分可能仍未执行。例如:

cljs.user> (try (map #(if (zero? %) (throw "some error")) [1]))
(nil)
cljs.user> (try (map #(if (zero? %) (throw "some error")) [0]))
; script fails with "Uncaught some error"

在这种情况下,map创建了一个惰性序列,try函数将其返回。然后,当repl尝试将序列打印到控制台时,它会被评估并且错误会在try表达式之外被抛出。

2
你也可以使用:default来捕获它们,这可能更符合惯用语。 - olieidel

4
我认为我在这个链接中找到了解决方案 https://groups.google.com/forum/#!topic/clojure/QHaTwjD4zzU 我将内容复制在此处: 这个解决方案是由Herwig Hochleitner发布的。

try在ClojureScript中实际上是使用内置的try*宏并添加类型分派。因此,要捕获所有内容,只需使用(try* ...(catch e ...))。这直接映射到JavaScript的try。

以下是我的实现,现在可以工作:
(defn is-dir? [the_dir]
  (try*
    (if-let [stat (.statSync fs the_dir )]
      (.isDirectory stat)
      false)
    (catch  e 
      (println "catching all exceptions, include js/exeptions")
      false
      )
    )
  )

我希望这能对你有所帮助
Juan


try* 已经被弃用,请使用 :default,就像你在另一个答案中所示。 - johnbakers

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