问题
I am trying to make a function that takes a file path and returns its content as a string. Here is my code snippet:
(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))
- Is using
def
correct/idiomatic on line 4? - After calling this function with a valid file path, I get the following error:
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)
Weirdly enough, if I call the function again I get the desired string content of the file! What is going on here?
EDIT: Here is the corrected function:
(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:
No, using def anywhere but at the root scope of your source is generally a bad idea and not idiomatic. If you want to create another local variable then another
let
expression is the way to go.For why its working sometimes, you are taking an async function and trying to make it synchronous. This is leading to race conditions. Sometimes the File System is returning the file before you return from the function (and that is why works) and sometimes it is not (error).
There are a few options:
You can try to make the function synchronous by using node's
readFileSync
function. That way you can just return what it returns.Instead of trying to extract the data in the
go
block, you should return thechan
you are putting to>!
and have the next function get the data from the channel in its own go block<!
. This is much more idiomatic than callbacks when using core.async.
来源:https://stackoverflow.com/questions/34557266/clojurescript-nodejs-function-that-returns-the-string-content-of-a-file