我正在处理JS中一个非常有问题的函数,该函数调用回调函数迭代次。特别是,该函数接受一个yaml字符串并为在字符串中找到的每个数量的yaml文档运行一个回调函数:
var yaml = require('js-yaml');
yaml.safeLoadAll(data, function (doc) {
console.log(doc);
});
所以在这里,如果data
包含2个yaml文档,那么我们将在控制台中看到2个日志。
假设string
有一个未知数量的yaml文档。我想使用core.async频道将每个文档放入一个javascript数组中。
首先,我创建了一个将每个yaml文档绑定到一个频道的函数:
(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
)
)
然后我创建了一个函数,它从通道中吸取每个yaml文档并将它们粘贴到一个javascript数组中(封装在另一个通道中)。
(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
)
)
然后我尝试执行结果:
(go (println <! (yaml-chan->yaml-array-chan (yaml-string->yaml-chan string)))
我得到的只是#object[cljs.core.async.impl.channels.ManyToManyChannel]
:(我认为它是因为我从未关闭yaml对象的原始通道。但是我如何使用该迭代回调函数执行此操作?在何处以及如何执行此操作我关闭那个频道?
答案 0 :(得分:1)
我不认为core.async会在这种情况下帮助很多。这在普通的javascript中也很难。只要有更多要加载的文档,safeLoadAll
就会在回调时触发。除了使用某种不稳定的超时检查之外,没有办法知道它是否已完成(这不会保证所有内容都已加载,只是在时间阈值内没有发生任何活动)
如果您不需要将所有文档收集到一个数组中,那么您可以使用core.async通道处理来处理每个结果。如果你真的需要一个数组,那么你应该找到另一个方法(循环遍历所有文档并单独加载它们),这样你就可以确定所有文件加载完成后的。
答案 1 :(得分:0)
我不会让你的回调在每次调用时生成一个通道。相反,我会创建一个函数,它关闭一个你作为回调传入的通道。然后将所有文档推送到此频道,然后您可以在准备好后阅读该文档以获取文档。