我正在尝试创建一个采用文件路径并将其内容作为字符串返回的函数。这是我的代码片段:
(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))
def
正确/惯用?TypeError :(中间值)(中间值)(中间值 值)(...)。call不是函数 在副本:99:6 在tryToString(fs.js:414:3) 在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
答案 0 :(得分:1)
不,在任何地方使用def但是在源的根范围内通常是一个坏主意而不是惯用语。如果你想创建另一个局部变量,那么另一个let
表达式就可以了。
为什么它有时工作,你正在采用异步功能并尝试使其同步。这导致了竞争条件。有时文件系统在从函数返回之前返回文件(这就是为什么有效),有时它不是(错误)。
有几个选择:
您可以尝试使用节点的readFileSync
功能使该功能同步。这样你就可以返回它返回的内容。
您应该返回go
的{{1}}而不是尝试提取chan
块中的数据,并让下一个函数从中获取数据频道在其自己的块>!
中。当使用core.async时,这比回调更加惯用。