0

I'm working on a tutorial: http://coenraets.org/blog/2012/10/creating-a-rest-api-using-node-js-express-and-mongodb/

I need some help with understanding syntax. Below is the code:

var mongo = require ('mongodb');

var Server = mongo.Server,
    Db = mongo.db,
    BSON = mongo.BSONPure;


var server = new Server ('localhost', 27017, {auto_reconnet:true});
db = new Db('winedb', server);


db.open(function(err, db) {
    if(!err) {
        console.log("Connected to 'winedb' database");
//Q1.  Why are we passing "collection" ?  Where did we declare "collection"?
        db.collection('wines', {strict:true}, function(err, collection) {
            if (err) {
                console.log("The 'wines' collection doesn't exist. Creating it with sample data...");
                populateDB();
            }
        });
    }
});

exports.findById = function(req, res) 
{
    var id = req.params.id;
    console.log('Retrieving wine: ' + id);
//Q2.  Why do we need to pass function as a parameter?  Where is "collection" declared?
    db.collection('wines', function(err, collection) 
    {
        collection.findOne({'_id':new BSON.ObjectID(id)}, function(err, item) 
        {
            res.send(item);
        });
    });
}

exports.findAll = function(req, res) {
    db.collection('wines', function(err, collection) {
//Q3.  Why do we not have to declare "items" anywhere?
        collection.find().toArray(function(err, items) {
            res.send(items);
        });
    });
};

Three Questions:

Q1: Why are we passing "collection" ? Where did we declare "collection"?

Q2: Why do we need to pass function as a parameter? Where is "collection" declared?

Q3: Why do we not have to declare "items" anywhere?

4 Answers 4

1

Q1: Why are we passing "collection" ? Where did we declare "collection"?

collection is a property (method actually) of the db object created on this line:

db = new Db('winedb', server);

Check the mongodb api to see how it should be used.


Q2: Why do we need to pass function as a parameter? Where is "collection" declared?

Dabatabase queries are very slow. It would not make sense for your program to wait for the result of a query to come before it continues execution, so the query is made in parallel with the other code. The problem you probably see with this is: if the execution is forked at that point, how do i get the result of my query? The answer is callbacks.

You need to pass a function to the collection method which it will call when the result is ready. The result is passed as a parameter to your function. A very schematic implementation of the collection method is:

function collection(name, callback) {
  var result = // do stuff to get the result;  
  callback(result);
}

Obviously there's more to it than this, but that is the main idea.

So to recap: you need to pass a function as a parameter in order to receive the result. The collection parameter in your function will be filled by the db.collection method with the result of the query (if there is no error).


Q3: Why do we not have to declare "items" anywhere?

This question betrays a lack of understanding of functions.

This is a function declaration:

function foo(bar) {}

bar is declared right there, it is a parameter of your function. Its value depends on how the function is called:

foo(5); // bar will be 5

If you wanted to ask where does the value of items come from, then the answer would be from the database, the toArray() method is similar to what i described on Q2. It takes a callback and calls it with the proper values.

Sign up to request clarification or add additional context in comments.

Comments

1

This style is necessary because operations in node.js that involve I/O (like database queries) are asynchronous, so the methods for those operations provide their results back to the caller via callback functions instead of return values.

collection and items are both parameters to the anonymous callback function that's passed as a parameter to the asynchronous functions. You could name those parameters whatever you want as only their position in the parameter list matters. Those callback functions will be called when the asynchronous result is available.

Comments

1

A1: collection is field or property in db object - it declared there.

A2: db.collection('wines', function(err, collection){}); We pass function as parameter because this is callback pattern.

It is mean you register function as listener and when db fetch data then call your function with err or collection. If operation is success err will be empty and you receive only collection

A3:describe in A2 collection eq items

Comments

1

All three of your questions stem back to a single concept: callbacks. Callbacks are generally used when a method is asynchronous and needs to provide you with a way of executing code after it is finished doing what it's doing. In all three cases, you are not passing values into a function, you are instead declaring the signature of a method that will be called at a later date. Here's a small example that might be easier to understand:

function asyncMethod(color, callback){
    var statement = 'My favorite color is ' + color;
    callback(statement);
}

asyncMethod('red', function(statementParam){
    console.log(statementParam);
});

You can see in that example that statementParam was never declared using var anywhere, instead it is actually the parameter to an unnamed function that is being passed as an argument to asyncMethod. The same thing could be also written like this:

function asyncMethod(color, callback){
    var statement = 'My favorite color is ' + color;
    callback(statement);
}

var callbackFunction = function(statementParam){
    console.log(statementParam);
};

asyncMethod('red', callbackFunction);

Now, if we take a look at one of the examples in your question

db.collection('wines', function(err, collection) 
{
    collection.findOne({'_id':new BSON.ObjectID(id)}, function(err, item) 
    {
        res.send(item);
    });
});

we could actually re-write it like this:

var callbackFunction = function(err, collection) {
    var secondCallbackFunction = function(err, item){
        res.send(item);
    };

    collection.findOne({'_id':new BSON.ObjectID(id)}, secondCallbackFunction);
};

db.collection('wines', callbackFunction);

It's pretty clear what is happening here, now. The "undefined" variables are actually parameters to newly defined functions, which are then immediately passed into mongodb driver's methods. Once the driver has finished doing what you've requested, it will execute your provided callback, passing in variables as appropriate.

Comments

Your Answer

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.