【问题标题】:Idiomatic conversion of node.js APIs to ClojureScriptnode.js API 到 ClojureScript 的惯用转换
【发布时间】:2016-09-02 11:52:51
【问题描述】:

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

当然,我可以像编写 JavaScript 一样编写 ClojureScript,但我想知道 ClojureScript 对回调风格的 API、流、EventEmitters 有什么作用,以及我如何以一种方式围绕 node.js API 编写包装器在 ClojureScript 中看起来并不陌生。

具体来说:

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

【问题讨论】:

    标签: javascript node.js clojure electron clojurescript


    【解决方案1】:

    根据我的经验,处理这些问题的最简单方法是使用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))
    

    我将结果传递给通道,即使该结果是错误的。这样,调用者可以通过doing来处理错误。例如:

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

    【讨论】:

    • try/catch 示例是否按原样与第一个 sn-p 一起工作,无需更改?
    • 是的。基本上, js/Error 的实例,如果是,则重新抛出它。
    【解决方案2】:

    我认为您的问题的答案是“视情况而定。”。

    始终考虑所有选项。仅仅因为core.async 在一种环境中有意义并不能使它成为所有地方的最佳选择。

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

    core.async 非常适合像流这样的事情,在这些事情中,您会获得想要累积成最终结果的特定事件链(例如,"data","data","data","close","end")。

    Promise 也是另一种选择。

    您需要的协调越多,core.async 的意义就越大。如果您不需要任何替代方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-14
      • 1970-01-01
      • 2019-11-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多