2

I'm working with mongojs and I have to retrieve a field from an object taken from mongodb. I can not understand how to return the field:

 function retrieveVertById(id){
 var result = [];
 db.clusters.find({id: id}, function (err, clusters){
 if( err || !clusters) console.log("No cluster found");
 else clusters.forEach( function (cluster) {
 vert = cluster["vertices"];
 result.push(vert);
 console.log(result);
 });
 })
return result;
};
var a = retrieveVertById("001");
console.log(a);

The print inside the 'forEach' prints the correct value: (ex. [ [ [ 8, 2, 2 ], [ 2, 2, 5 ], [ 2, 2, 2 ], [ 5, 2, 2 ] ] ] ) On the contrary the print outside the cycle shows an empty array. what does not work with the return? Thanks in advance for your help.

Alberto De Caro
5,2039 gold badges50 silver badges76 bronze badges
asked Apr 27, 2013 at 15:29
5
  • console.log(vert) is ok? Commented Apr 27, 2013 at 15:33
  • Yes, also console.log(vert) in the forEach prints the correct value. Commented Apr 27, 2013 at 15:39
  • Could you explain your question a little better? By print do you mean the console.log? Which console.log is not showing the right value, a or return result, did you make your own id` or are you mistaken for _id? Commented Apr 27, 2013 at 15:40
  • 1
    You can't return the result of an asynchronous operation like find from a function. You have to use callbacks as your retrieveVertById function returns before the find callback occurs. Do some searches of existing questions as this is a very common point of confusion. Commented Apr 27, 2013 at 15:44
  • For print I mean the instruction 'console.log'. The right value is shown only in the forEach. It seems that 'return' has no effect because the instruction 'console.log(a)' shows an empty array instead of the instruction 'console.log(result)' that shows the correct value. Commented Apr 27, 2013 at 15:46

2 Answers 2

1

I've not used mongojs, but any db lookup will almost certainly be asynchronous. This means the function you passed to db.clusters.find will not run immediately, but rather when the asynchronous call returns from mongo. Instead of returning a value from retrieveVertById, try a callback function instead:

function retrieveVertById(id, successCallback) {
 db.clusters.find({
 id: id
 }, function (err, clusters) {
 if (err || !clusters) {
 console.log("No cluster found");
 } else {
 var result = [];
 clusters.forEach(function (cluster) {
 vert = cluster["vertices"];
 result.push(vert);
 });
 successCallback(result);
 }
 });
};
retrieveVertById("001", function(result) {
 console.log(result);
});
answered Apr 27, 2013 at 15:50
Sign up to request clarification or add additional context in comments.

5 Comments

I was able to take the field with the callback Thank you very much for your time!
When I call retrieveVertById in the bottom of my example, I'm passing in the callback as an anonymous function. I gave retrieveVertById a second parameter called successCallback. So the line successCallback(result); actually calls the anonymous function: function(result) { console.log(result); } that I passed in as an argument. Understanding callback functions is a must when writing asynchronous programs.
@FrancescoMaglia - Glad to help! Be sure mark an accepted answer to close out this question.
Last question: How can I assign the returned value to a variable? I explain better: I want to do something like this: var vert = retriveVertById("001")
@FrancescoMaglia - Short answer: move the code that references that variable into the body of the callback. So function(result) { console.log(result); } becomes function(result) { var vert = result; //rest of your code }. Long answer: do some research on JavaScript callback functions. There's certainly too much to cover in a comment box.
0

oh, i see... you should remember that javascript is async language

return result;

after forEach() will not return result from inside forEach(). you should send result after last value parsed.

var i = 0;
clusters.forEach( function (cluster) {
 vert = cluster["vertices"];
 result.push(vert);
 if (i >= clusters.length)
 return result;
 i++;
});
answered Apr 27, 2013 at 15:46

1 Comment

Couple issues. Since there are several nested functions in this example, a return statement in the forEach body will not 'bubble-up' and act as a return for the retrieveVertById function. Second, if the db.cluster.find method is asynchronous as you said, then you can't return any values from it without the use of a callback function.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.