I need to get the list of files in a directory to the client in Meteor.
So far I've got this:
if (Meteor.isClient) {
Meteor.call('getFiles', function(error, result) {
if (error) {
throwError(error.reason);
} else {
console.log(result);
}
});
}
if (Meteor.isServer) {
Meteor.methods({
'getFiles': function getFiles() {
var walk = Meteor.npmRequire('walk');
var files = new Array();
var walker = walk.walk('/test', { followLinks: false });
walker.on('file', function(root, stat, next) {
files.push(root + '/' + stat.name);
next();
});
walker.on('end', function() {
console.log(files);
});
return files;
}
});
}
I can see the list of files on the server console, but the client's console returns an empty array. I'm guessing this is because the method gets called before finishing the walker, and simply returns the empty array that's created in the method.
My question is, how do I make this reactive? I want this method to run every time I add or delete a file in the directory.
There are two things you need to do to achieve your goal.
1) Make the Meteor method wait for the asynchronous result,
2) Make the result update when file structure changes.
The first one is relatively easy, and typically achieved with Futures. See the method code this MeteorPad:
Future = Npm.require('fibers/future');
Meteor.methods({
async: function() {
var fut = new Future();
Meteor.setTimeout(function() {
fut.return('Async world!');
}, 2000);
return fut.wait();
},
});
For the second one, things are more complicated and cannot be achieved via method, unless you refresh the results manually from time to time.
First of all, your app needs to be notified when file structure changes. For this you need a package to monitor file system, not just walk through existing files. chokidar is a tool of choice.
Now the problem is that when file system has changed and you received an event, the method has returned long time ago and is forgotten, so you cannot use it to propagate the event to the client. You need a different tool. I can think of three possibilities.
The standard one would be to create a custom publication on the server and subscribe to it. This is the best solution, though not the easiest one to start with. See the example in documentation.
An easy workaround is to copy the file structure to a collection in Mongo database and simply subscribe to that collection. This might be the easiest choice for simple projects.
You can also use a package like anit:methods to notify client of the event, though with this solution you won't get reactivity out of the box - you will need to manage dependencies manually on the client side.