1 The Problematic JavaScript Function
I am dealing with a very problematic function in JS that invokes a callback function an iterated number of times. In particular, the function takes a yaml string and runs a callback function for each number of yaml documents found within the string:
var yaml = require('js-yaml');
yaml.safeLoadAll(data, function (doc) {
console.log(doc);
});
So here, if data
contains 2 yaml documents, then we will see 2 logs in our console.
2 Dealing with it in ClojureScript
Suppose that string
has an unknown number of yaml documents. I'd like to place each of these documents into a javascript array using a core.async channel.
First, I make a function which jams each yaml document into a channel:
(defn yaml-string->yaml-chan [string]
(let [c (chan)]
(go
(.safeLoadAll
yaml
string
(fn [current-yaml-object]
(go
(>! c current-yaml-object)
;(close! c) ; cant close here or we only get one doc!
)
))
) c ; here we return the channel
)
)
Then I make a function which sucks up each yaml document from the channel and sticks them into a javascript array (encapsulated in another channel).
(defn yaml-chan->array-chan [c]
(let [arr (js/Array.) arr-chan (chan) a (atom true)]
(go
(reset! a (<! c))
(while (not-nil? @a)
(.push arr @a)
(reset! a (<! c))
)
(>! arr-chan arr)
) arr-chan
)
)
Then I attempt to execute the result:
(go (println <! (yaml-chan->yaml-array-chan (yaml-string->yaml-chan string)))
And all I get is #object[cljs.core.async.impl.channels.ManyToManyChannel]
:( I think it's because I never closed the original channel for the yaml objects. But how do I do this with that iterated callback function? Where and how do I close that channel?