Clojurescript异步<?宏

4
我经常看到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))))

在这篇博客文章中:
(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)))))

<?只是一个宏,会扩展成类似于(throw-err (<! [expr]))的东西。在core.async中,<!与ES6的yield操作符具有相同的作用。如果异步进程将错误写入其通道,我们将将其转换为异常。

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


1
FYI:他的所有代码都在Github上:https://github.com/swannodette/swannodette.github.com 你要找的文件是:macros.cljhelpers.cljs - ClojureMostly
@Andre谢谢!我正在寻找那个!(在GitHub上搜索<?不起作用) - nha
1个回答

2

好的,这里是目前我使用的内容。可能还有改进的空间。

在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看起来应该会抛出一个错误,但它并不总是这样做)。


1
工作线程中的异常不一定会有任何提示告诉你它们已经发生。Stuart Sierra在他的博客文章中展示了一些设置,可以确保您在异步世界中实际上看到错误。"在JVM中,当除主线程以外的线程抛出异常时,如果没有任何东西来捕获它,什么也不会发生。线程会默默地死亡。" - noisesmith
<?需要是一个宏吗? - koddo
1
回答我自己的问题,是的,它不能是一个函数,因为<! 必须在go块内。 - koddo

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