将node.js API惯用转换为ClojureScript

时间:2016-09-02 11:52:52

标签: javascript node.js clojure electron clojurescript

我正在编写一个Electron应用程序,在这个应用程序中,我需要与一些Node.js API进行交互 - 读取文件,获取目录条目,监听事件。

当然,我可以用编写JavaScript的方式编写ClojureScript,但我想知道ClojureScripts对回调式API,流,EventEmitters的看法是什么,以及如何以一种方式编写有关node.js API的包装器不要在ClojureScript中看起来很陌生。

具体来说:

  1. 如何编写包含回调样式node.js API的API。 (比如,fs.readdir
  2. 如何与类似EventEmitter的API进行交互?
  3. (可能接近第2页)如何使用node.js流API?

2 个答案:

答案 0 :(得分:8)

根据我的经验,处理这些问题的最简单方法是使用core.async

回调风格

例如,阅读目录:

(def fs (js/require "fs"))

(defn read-dir [path]
  (let [out (async/chan)]
    (.readdir fs path
      (fn [err files]
        (async/put! (if err err files))
        (async/close! out)))
    out))

我将结果传递给通道,即使该结果是错误的。这样,调用者可以通过执行来处理错误。 E.g:

(let [res (<! (read-dir "."))]
  (if (instance? js/Error res)
    (throw res)
    (do-something res))

在我自己的项目中,我使用cljs-asynchronize,它允许您将NodeJS回调样式函数转换为core.async兼容函数。例如,这与第一个示例相同:

(defn read-dir [path]
  (asynchronize 
    (.readdir fs path ...)))

最后,为了更好地通过渠道处理错误,我个人发现"Error Handling with Clojure Async"非常有用。因此,您可以编写上面的错误处理代码,如:

(try 
  (let [res (<? (read-dir "."))]
    (do-something res))
  (catch js/Error e
    (handle-error e))

<强>流

Stream API甚至更简单:

(defn create-read-stream [path]
   (let [out (async/chan)
         stream (.createReadStream fs path)]
     (.on stream "close" #(async/close! out))
     (.on stream "data" #(async/put! out %))
     out))

答案 1 :(得分:1)

我认为你的问题的答案是&#34;这取决于。&#34;。

始终考虑所有选项。仅仅因为core.async在一个设置中有意义并不能使它成为最佳选择。

如果仅调用一次并且不需要与其他任何东西协调(例如。fs.readdir),则可以使用普通回调。

core.async非常适合流媒体,因为您可以获得想要累积到最终结果中的特定事件链(例如。"data","data","data","close","end")。

承诺也是另一种选择。

您需要的协调越多,core.async越有意义。如果您不需要考虑替代方案。