I'm using the ntwitter node.js module to access twitter's streaming API from inside a meteor app, but when trying to insert into a collection inside the callback function the app crashes:
twitter.stream('statuses/filter', {'track':'whatever'}, function(stream) {
stream.on('data', function (data) {
//logging the data coming back works fine
console.log(data);
//the next line throws "Error: Meteor code must always run within a Fiber"
Tweets.insert(data);
});
});
Is there a recommended approach to using async callbacks in the context of Meteors linear execution model? I tried wrapping the insertion inside a new Fiber which seems to work but I'm unsure of any implications it may have.
I found this http://gist.io/3443021 which was helpful but I'm still not sure which approach would suit my particular case so any help would be appreciated.
Cheers
We used a different design pattern. In the async callback, we act more like a device driver and simply buffer the result in memory:
var tweets = [];
twitter.stream('statuses/filter', {'track':'whatever'}, function(stream) {
stream.on('data', function (data) {
//logging the data coming back works fine
console.log(data);
//the next line throws "Error: Meteor code must always run within a Fiber"
tweets.push(data);
});
});
and then later on, back within the normal Meteor execution environment within a Fiber, either in a timer or a result of a function, we drain the tweets array and do the insert then. A Javascript array doesn't care whether it is running within a Fiber or not.
In our case, we are doing this with asynch IMAP email rather than tweets, but the analogy still holds.
Wrap your callback in Meteor.bindEnvironment like so:
twitter.stream('statuses/filter', {'track':'whatever'}, function(stream) {
stream.on('data', Meteor.bindEnvironment(function (data) {
//logging the data coming back works fine
console.log(data);
//the next line throws "Error: Meteor code must always run within a Fiber"
Tweets.insert(data);
}));
});
According to this SO post about Async wrappers on the Meteor Server, you want to use Meteor.bindEnvironment when you are managing a callback using a third party api/npm module (which looks to be the case)
Meteor.bindEnvironment creates a new Fiber and copies the current Fiber's variables and environment to the new Fiber.