Die*_*ons 9 recursion asynchronous node.js meteor
我有一个递归函数,它在服务器端异步构建一个树,我想"观察"它并在每次发生更改时重新运行Meteor中的调用方法.
我做了一个简化的例子,用一个递归的readdir调用构建一个树(在实际的应用程序中,每个节点可能需要几分钟的计算,其结果取决于已经探索过的节点)
在server/methods.js中
var fs = Meteor.npmRequire('fs')
var path = Meteor.npmRequire('path')
var tree = function (dir, r) {
try
{
fs.readdir (dir, function (error, files) {
if (files && files.length)
for (var i = 0; i < files.length; i++)
{
r[i] = { name : files[i], children : [] }
tree(path.resolve(dir, files[i]), r[i].children)
}
})
} catch (e) { console.log("exception", e)}
}
Meteor.methods({
'build_tree' : function () {
var r = []
tree("/tmp/", r)
return r // Wrong !
}
})
Run Code Online (Sandbox Code Playgroud)
在client/client.js中
Meteor.call('build_tree', function (error, result) {
console.log(error, result)
}
Run Code Online (Sandbox Code Playgroud)
我已经在https://www.discovermeteor.com/patterns/5828399的代码的其他部分使用了期货.
但在这种情况下,我因某种原因而失败
我想到的唯一解决方法是逐步将异步结果插入"扁平"Mongo集合中,并在客户端将其作为树进行反应性重建.
Die*_*ons 10
我设法做到了这一点
[关闭列表标记或代码格式不正确]
Future = Meteor.npmRequire('fibers/future')
FS = Meteor.npmRequire('fs')
Path = Meteor.npmRequire('path')
const all_files = []
const future = new Future()
const to_process = [dir]
let started = 0
let ended = 0
const tree = function () {
while (to_process.length) {
let dir = to_process.pop()
started++
FS.readdir (dir, function (error, files) {
if (error) {
if (error.code == 'ENOTDIR') all_files.push(dir)
}
else if (files && files.length)
{
for (let i = 0, leni = files.length; i < leni; i++)
{
let f = Path.resolve(dir, files[i])
to_process.push(f)
}
}
ended++
tree()
})
}
if (!to_process.length && started == ended)
future['return']()
}
tree()
future.wait()
Run Code Online (Sandbox Code Playgroud)
它没有"渐进式更新"的感觉,你可以通过更新数据库并让反应性来管理它,因为所有的计算都在等待最后的Future['return']()
但是代码更简单和自包含.
那确实非常复杂.首先,当您的树代码运行异步时,您需要提供成功回调/解决承诺/返回未来或其他内容,以便您可以控制Meteor方法何时返回.然后你需要使用Futures来推迟返回你得到结果的方法.
但即便如此,我也看不到服务器应该知道某些事情发生了变化.
我想到的唯一解决方法是逐步将异步结果插入"扁平"Mongo集合中,并在客户端将其作为树进行反应性重建.
这实际上是一个可行的直接解决方案.