Как поймать любое исключение Javascript в Clojurescript?

На моем коммуникационном уровне мне нужно иметь возможность перехватывать ЛЮБОЕ исключение javascript, регистрировать его и действовать, как обычно. Текущий синтаксис для перехвата исключений в Clojurescript диктует, что мне нужно указать тип перехватываемого исключения.

Я пытался использовать nil, js/Error, js/object в форме catch, и он не перехватывает ЛЮБОЕ исключение javascript (которое может иметь строку в качестве типа объекта).

Буду признателен за любые подсказки, как это можно сделать изначально в Clojurescript.


person Dima B.    schedule 29.09.2012    source источник
comment
Привет Дима! Как вы думаете, мой ответ решит вашу проблему?   -  person tangrammer    schedule 21.10.2013


Ответы (3)


Я нашел еще один возможный ответ в "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))
person tangrammer    schedule 17.01.2014
comment
Теперь это правильный способ сделать это. - person johnbakers; 11.05.2014
comment
:default в настоящее время не существует в обычном (на основе Java) Clojure, но есть предложение добавить его и туда: dev.clojure.org/jira/browse/CLJ-1293 - person Hutch Moore; 22.03.2017
comment
#?(:cljs :default :clj Throwable) вместо :default будет работать как для clj, так и для cljs в файле cljc - person Chris Murphy; 28.10.2020

Похоже, 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.

person bmaddy    schedule 28.02.2013
comment
вы также можете поймать их с помощью :default, что, вероятно, более идиоматично - person olieidel; 30.01.2018

Кажется, я только что нашел решение по этой ссылке https://groups.google.com/forum/#!topic/clojure/QHaTwjD4zzU

Я копирую содержимое сюда: Это решение было опубликовано Herwig Hochleitner.

try в clojurescript на самом деле является макросом, который использует встроенный try* и добавляет диспетчеризацию типов. Итак, чтобы поймать все, просто используйте (try* ... (catch e ...)). Это сопоставляется непосредственно с попыткой javascript.

И вот моя реализация работает сейчас:

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

Надеюсь, это поможет вам
Хуан

person tangrammer    schedule 11.09.2013
comment
try* теперь устарел. Используйте :default как в вашем другом ответе - person johnbakers; 11.05.2014