1

I can't figure out why the fetch function is not returning the information I wish to have:

(function(){
    var root = this;
    var Database = root.Database = {};

    var Db = require('mongodb').Db,
    Connection = require('mongodb').Connection,
    Server = require('mongodb').Server;

    var host = process.env['MONGO_NODE_DRIVER_HOST'] != null ? process.env['MONGO_NODE_DRIVER_HOST'] : 'localhost';
    var port = process.env['MONGO_NODE_DRIVER_PORT'] != null ? process.env['MONGO_NODE_DRIVER_PORT'] : Connection.DEFAULT_PORT;

    // Require Underscore, if we're on the server, and it's not already present.
    var _ = root._;
    if (!_ && (typeof require !== 'undefined')) _ = require('./underscore');



    Database.ActiveRecord = function(attributes, collection){
        this.collection = collection;
        this.cid = _.uniqueId('c');
        attributes || (attributes = {});
        this.attributes = attributes;
    };

    // Connecting to database and setting the connection as a shared variable among ActiveRecords
    console.log("Connecting to " + host + ":" + port);

    Database.ActiveRecord.prototype.db = new Db('node-mongo-eslip', new Server(host, port, {}));

    _.extend(Database.ActiveRecord.prototype, {

        initialize: function(){},

        // Returns `true` if the attribute contains a value that is not null
        // or undefined.
        has: function(attr) {
            return this.attributes[attr] != null;
        },

        // Sets attributes
        set: function(key, value){
            var attrs, attr, val;
            if(_.isObject(key) || key == null){
                throw Error("The key should not be an object or null");
            }else{
                attrs = {};
                attrs[key] = value;
            }

            if (!attrs) return this;

            var now = this.attributes;

            for(attr in attrs){
                val = attrs[attr];
                if(!_.isEqual(now[attr], val)) now[attr] = val;
            }
        },

        unset: function(key){
            return this.set(attr, null);
        },

        toJSON: function() {
            return _.clone(this.attributes);
        },

        fetch: function(query, fields, options){
            var record = this;
            record.db.open(function(err, db){
                if(!(record.collection||(typeof record.collection === 'string'))) throw Error('You should define a name attribute, which represents the collection of the Database');
                db.collection(record.collection, function(err, collection){
                    console.log('Fetching...');
                    collection.find(query, fields, options).toArray(function(err, docs) {
                        return docs;
                    });
                });
            });
        },

        save: function(){
            var record = this;
            record.db.open(function(err, db){
                if(!(record.collection||(typeof record.collection === 'string'))) throw Error('You should define a name attribute, which represents the collection of the Database');
                db.collection(record.collection, function(err, collection){
                    collection.insert(_.clone(record.attributes), {safe:true},
                    function(err, objects) {
                        if (err) console.warn(err.message);
                        if (err && err.message.indexOf('E11000 ') !== -1) {
                            console.log('This id has already been inserted into the database');
                        }
                    });
                });
                console.log('Saved!');
            });
        }
    });
}());

I've spend quite some time trying to figure out what is missing, and didn't make it, maybe someone would have better odds of figuring out.

1
  • 2
    Welcome to the wonderful world of async! You can't do that. Commented Feb 7, 2012 at 1:27

2 Answers 2

1

By the time the callback function from which you're trying to run return docs is being executed, the external fetch function has already returned -- as @SLaks suggested, welcome to the wonderful world of asynchronous programming.

Promises can be an excellent way for dealing with asynchronous code -- they're available in jQuery, Dojo, and other libraries and toolkits. Your fetch method could return a promise, and code that called the fetch method could react when the returned promise was "resolved". Here's what that looks like with Dojo:

    fetch: function(query, fields, options){
        var record = this, dfd = new dojo.Deferred;

        record.db.open(function(err, db){
            if(!(record.collection||(typeof record.collection === 'string'))) throw Error('You should define a name attribute, which represents the collection of the Database');
            db.collection(record.collection, function(err, collection){
                console.log('Fetching...');
                collection.find(query, fields, options).toArray(function(err, docs) {
                    dfd.resolve(docs);
                });
            });
        });

        return dfd.promise;
    },

Then, code that called fetch might look like this:

myDB.fetch().then(function(docs) {
  // do whatever you need with the docs
});
Sign up to request clarification or add additional context in comments.

1 Comment

I actually modified the fetch function so that it supports a callback function. It's working just fine now. howtonode.org/express-mongodb was my reference for those in need.
1

You can't do that, because in JS, function's expression return XXXX; means that the control flow returns to the outer function. For example:

(function(){
    function foo(){
        return "inner";
    }
    foo();
})();

The outer function really returns nothing. Because the function foo just returns the control flow to the outer function without the info of "inner".

If you want to return something, move it to the scope of outer function. That will return what you want.

Hope it helps.

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.