ClojureScript(nodejs)函数表示returns一个文件的字符串内容

ClojureScript (nodejs) function that returns the string content of a file

我正在尝试制作一个函数,该函数采用文件路径和 returns 其内容作为字符串。这是我的代码片段:

(defn get-string-from-file-path [path]
  (let [fs (node/require "fs") c (chan)]
      (.readFile fs path "utf8" (fn [err data] ((go (>! c (str data))))))
      (go (def r (str (<! c)))) ; is using def correct here?
       r))
  1. 是否在第 4 行使用 def correct/idiomatic?
  2. 使用有效的文件路径调用此函数后,出现以下错误:

TypeError: (intermediate value)(intermediate value)(intermediate value)(...).call is not a function at repl:99:6 at tryToString (fs.js:414:3) at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:401:12)

奇怪的是,如果我再次调用函数 ,我将获得所需的文件字符串内容!这是怎么回事?

编辑: 这是更正后的函数:

(defn get-string-channel-from-file-path [path] ; function is now "get string channel" instead of "get string"
  (let [fs (node/require "fs") c (chan)]
      (.readFile fs path "utf8" (fn [err data] (go (>! c data))))
        c)) ; return channel instead of string
  1. 不,在源代码的根范围以外的任何地方使用 def 通常是个坏主意,而且不符合习惯。如果你想创建另一个局部变量,那么另一个 let 表达式是可行的方法。

  2. 为什么它有时会起作用,你正在使用异步函数并试图使其同步。这会导致竞争条件。有时,文件系统会在您 return 从函数中 return 之前 returning 文件(这就是为什么有效),有时却不是(错误)。

有几个选项:

  • 你可以尝试使用节点的readFileSync函数使函数同步。这样你就可以 return 它 returns.

  • 而不是尝试提取 go 块中的数据,您应该 return 您要放入 >!chan 并且下一个函数在它自己的 go 块 <! 中从通道获取数据。在使用 core.async.

  • 时,这比回调更惯用