[cljs-node-io "1.1.2"]
cljs-node-io {:mvn/version "1.1.2"}
This is a port of clojure.java.io to clojurescript, in a way that makes sense for nodejs. The goal is to make the clojure programmer feel right at home, so most everything has the same signatures and semantics as their jvm counterparts. However many things necessarily work differently internally, and with some consequence. You can read about the differences here
(require '[cljs-node-io.core :as io :refer [slurp spit]])
(def data [{:foo 42} {:foo 43}])
(spit "data.edn" data)
(= data (read-string (slurp "data.edn"))) ;=> true
;; write asynchronously using core.async
(go
(let [[err] (<! (io/aspit "data.edn" data))]
(if-not err
(println "you've successfully written to 'data.edn'")
(println "there was an error writing: " err))))
;; read asynchronously using core.async
(go
(let [[err datastring] (<! (io/aslurp "data.edn"))]
(if-not err
(handle-data (read-string datastring))
(handle-error err))))
In the nodejs fs module, functions are asynchronous by default, and their synchronous versions have names with a Sync
suffix. In cljs-node-io, functions are synchronous by default, and async versions have an a
prefix. For example, cljs-node-io.core/slurp
is synchronous (just as jvm), whereas cljs-node-io.core/aslurp
runs asynchronously. This convention simply saves you some thought cycles at the repl. Note that most of the time (scripting...) synchronous functions are fine and getting order guarantees from async code is not worth the hassle
[?err]
or [?err ?data]
depending on the operation(go
(let [[err data] (<! afn)]
(if-not err
(handle-result data)
(handle-error err))))
read more here
(require '[cljs-node-io.fs :as fs])
(fs/touch "/tmp/hello")
;; BAD! maybe astat is run before arename
(def rc (fs/arename "/tmp/hello" "/tmp/world"))
(def sc (fs/astat "/tmp/world"))
(go
(let [[err] (<! rc)]
(if-not err
(let [[err st] (<! sc)]
(if-not err
(println (js/JSON.stringify st))
(throw err)))
(throw err))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; GOOD! chain the calls together
(go
(let [[err] (<! (fs/arename "/tmp/hello" "/tmp/world"))]
(if-not err
(let [[err st] (<! (fs/astat "/tmp/world"))]
(if-not err
(println (js/JSON.stringify st))
(throw err)))
(throw err))))
Node runs an asynchronous event loop & all IO is driven under the hood by libuv. Construction of streams involves creating a object within the js-vm and returning it to the user synchronously so that listeners may be attached. Calls to listeners are then scheduled using js/process.nextTick. This means you fundamentally cannot create a stream and consume it synchronously... you must instead create the stream and attach handlers to its emitted events.
To preserve synchronous semantics, slurp
for example uses memory consuming fs.readFileSync. This is fine for small files and repl sessions. If you need to read larger files, restructure your program to accommodate node streams. Luckily node streams mostly manage themselves.
no reader + writer types, not really necessary
no URL type, just goog.net.Uri
javascript does not have a character type
no java-style char/byte arrays, just nodejs buffers
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close