I have a (possibly dumb) problem with my code. I have something like this:
io.sockets.on('connection', function(socket)
{
var list = {};
socket.on('event', function(data){
if(!list[data.field_name]){
list[data.field_name] = [];
// db and collection already defined
var collection = new mongodb.Collection(db, coll);
collection.find({
field: data.field_name,
}).toArray(function(err, results){
list[data.field_name] = results[results.length-1];
socket.emit('another-event',{
list:list[data.field_name];
});
});
} else {
socket.emit('another-event',{
list:list[data.field_name];
});
}
});
}
I'm basically trying to cache the db results in list, and send it directly (without a db query), if it has already been retrieved from the database earlier.
The problem I'm having is that the assignment list[data.field_name] = results[results.length-1]
doesn't work. So if it has tried to retrieve the data before, list[data.field_name]
has been initialized to []
but it doesn't contain the data that is assigned to it after.
To be clear, it does retrieve the data from the db fine, and sends it to the client properly the first time when it is retrieved from the database. It's when I try to send the cached copy that the problem arises -- there is no cached copy.
I know this is something to do with nodejs (and the mongodb query) being asynchronous, but I can't seem to figure out how to make this work. Any help will be appreciated.
You are emitting another-event
before the query to the collection has completed. If the data has not yet been retrieved when another-event
is emitted then list[data.field_name]
will still be empty. Try something like:
io.sockets.on('connection', function(socket)
{
var list = {};
socket.on('event', function(data){
var anotherEvent = function() {
socket.emit('another-event',{
list:list[data.field_name];
});
};
if(!list[data.field_name]){
list[data.field_name] = [];
// db and collection already defined
var collection = new mongodb.Collection(db, coll);
collection.find({
field: data.field_name,
}).toArray(function(err, results){
list[data.field_name] = results[results.length-1];
anotherEvent();
});
} else {
anotherEvent();
}
});
}