我有一个递归函数,它在服务器端异步构建一个树,我想“观察”它,并且每次发生更改时都会重新运行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 !
}
})
客户端/ client.js中的
Meteor.call('build_tree', function (error, result) {
console.log(error, result)
}
我已经在基于https://www.discovermeteor.com/patterns/5828399的代码的其他部分使用了期货。
但在这种情况下,由于
,我不知何故失去了我想到的唯一解决方法是逐步将异步结果插入“扁平”Mongo集合中,并在客户端以树的形式反复重建它。
答案 0 :(得分: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()
它没有&#34;渐进式更新&#34;感觉你通过更新数据库并让反应性来管理它,因为所有的计算都在等待最后的Future['return']()
但代码更简单和自包含。
答案 1 :(得分:5)
那确实非常复杂。首先,当您的树代码运行异步时,您需要提供成功回调/解决承诺/返回未来或其他内容,以便您可以控制Meteor方法何时返回。然后你需要使用Futures来推迟返回你得到结果的方法。
但即便如此,我也看不到服务器应该知道某些事情发生了变化。
我想到的唯一解决方法是逐步将异步结果插入“扁平”Mongo集合中,并在客户端以树的形式反复重建它。
这实际上是一个可行的直接解决方案。