Clojurescript 异步 <?宏观

Clojurescript async <? macro

我一直在 swanodette 的代码中看到这个宏 <?,它看起来非常有用:

在此 gist 中:

;; BOOM!!! we can convert async errors into exceptions
(go (try
      (let [x (<? (run-task (.-readFile fs) "foo.txt" "utf8"))]
        (.log js/console "Success" x))
      (catch js/Error e
        (.log js/console "Oops" e))))

在此博客中 post :

(go (try
      (let [tweets    (<? (get-tweets-for "swannodette"))
            first-url (<? (expand-url (first (parse-urls tweets))))
            response  (<? (http-get first-url))]
        (. js/console (log "Most recent link text:" response)))
      (catch js/Error e
        (. js/console (error "Error with the twitterverse:" e)))))

<? is just a touch of macro sugar that expands into something like (throw-err (<! [expr])). In core.async <! serves the same purpose as ES6's yield operator. If an asynchronous process writes an error onto its channel we will convert it into an exception.

但我找不到它的定义。它在 Clojure{Script} 中是如何实现的?

好的,这就是我目前使用的。可能还有改进的余地。

在 Clojure 中:

(defn throw-err [e]
  (when (instance? Throwable e) (throw e))
  e)

(defmacro <? [ch]
  `(throw-err (<! ~ch)))

在 ClojureScript 中:

(defn error? [x]
  (instance? js/Error x))


(defn throw-err [e]
  (when (error? e) (throw e))
  e)

(defmacro <? [ch]
  `(throw-err (<! ~ch)))

虽然我完全不确定我的解决方案的可读性(throw-err 看起来它应该抛出一个错误,但它不会。至少不是每次)。