I'm new to JS in general, but I am trying to query some data from MongoDB. Basically, my first query retrieves information for the session with the specified session id. The second query does a simple geospacial query for documents with a location near the specified location.
I'm using the mongodb-native javascript driver. All of these query methods return their results in callbacks, so they're non-blocking. This is the root of my troubles. What I'm needing to do is retrieve the results of the second query, and create an Array of sessionIds of all the returned documents. Then I'm going to pass those to a function later. But, I can't generate this array and use it anywhere outside the callback.
Does anyone have any idea how to properly do this?
db.collection('sessions', function(err, collection) {
collection.findOne({'sessionId': client.sessionId}, function(err, result) {
collection.find({'geolocation': {$near: [result.geolocation.latitude, result.geolocation.longitude]}}, function(err, cursor) {
cursor.toArray(function(err, item) {
console.log(item);
});
});
});
I'm new to JS in general, but I am trying to query some data from MongoDB. Basically, my first query retrieves information for the session with the specified session id. The second query does a simple geospacial query for documents with a location near the specified location.
I'm using the mongodb-native javascript driver. All of these query methods return their results in callbacks, so they're non-blocking. This is the root of my troubles. What I'm needing to do is retrieve the results of the second query, and create an Array of sessionIds of all the returned documents. Then I'm going to pass those to a function later. But, I can't generate this array and use it anywhere outside the callback.
Does anyone have any idea how to properly do this?
db.collection('sessions', function(err, collection) {
collection.findOne({'sessionId': client.sessionId}, function(err, result) {
collection.find({'geolocation': {$near: [result.geolocation.latitude, result.geolocation.longitude]}}, function(err, cursor) {
cursor.toArray(function(err, item) {
console.log(item);
});
});
});
Share
Improve this question
edited Jan 10, 2011 at 16:57
James Gregory
14.2k2 gold badges45 silver badges60 bronze badges
asked Jan 10, 2011 at 2:47
RyanRyan
7,95711 gold badges66 silver badges119 bronze badges
2 Answers
Reset to default 6Functions are the only thing on javascript that "enclose" scope.
This means that the variable items in your inner callback function are not accessible on the outer scope.
You can define a variable in the outer scope so it will be visible to all the inner ones:
function getItems(callback) {
var items;
function doSomething() {
console.log(items);
callback(items);
}
db.collection('sessions', function(err, collection) {
collection.findOne({'sessionId': client.sessionId}, function(err, result) {
collection.find({'geolocation': {$near: [result.geolocation.latitude, result.geolocation.longitude]}}, function(err, cursor) {
cursor.toArray(function(err, docs) {
items = docs;
doSomething();
});
});
});
});
}
Node.js is asynchronous, so your code should be written to match it.
I've found this model useful. Each nested callback jumble is wrapped in helper function that calls the argument callback 'next' with error code and result.
function getSessionIds( sessionId, next ) {
db.collection('sessions', function(err, collection) {
if (err) return next(err);
collection.findOne({sessionId: sessionId}, function(err, doc) {
if (err) return next(err);
if (!doc) return next(false);
collection.find({geolocation: {$near: [doc.geolocation.latitude, result.geolocation.longitude]}}.toArray(function(err, items) {
return next(err, items);
});
});
});
}
Then in your calling code
getSessionIds( someid, _has_items);
function _has_items(err, items) {
if( err ) // failed, do something
console.log(items);
}