bhupen.chn bhupen.chn - 4 months ago 19
Node.js Question

Unable to define callback for async.forEachOf, express, mongoose

I am trying to fetch all databases from mongo, each database has a collection 'meta' that contains details of tasks. I want to send details of all tasks to the client.

Fairly new to node.js hence the hacky code, for the code below this is the response the I get.

Here
GET /tasks 304 8.283 ms - -
There [object Object]
GET /favicon.ico 304 1.084 ms - -


'Here' is logged before 'There'.
I am unable to define the callback for this.

// get list of tasks, basically list of dbs
app.get('/tasks', function (req, res) {
var connection = mongoose.createConnection('mongodb://localhost/temp');
connection.on('open', function() {
// connection established
new Admin(connection.db).listDatabases(function(err, result) {
console.log('listDatabases succeeded');
// database list stored in result.databases
var allDatabases = result.databases;
// iterate and add meta and completion
var sendData = new Array();
async.forEachOf(allDatabases, function(value, key, callback) {
var dbName = value.name;
console.log(dbName);
var result;
if(dbName!='local') {
var database_name = dbName;
var tempCon = mongoose.createConnection('mongodb://localhost/'+database_name);
var Meta = new mongoose.Schema({
originalname : { type: String, trim: true }
});
tempCon.model('meta', Meta).find({ task: { $ne: null } }, function(err, doc) {
result = doc[0].toObject();
var obj = {
"task_hash" : database_name,
"task_info" : result
};
sendData.push(obj);
console.log("There "+sendData);
});
}
});
console.log("Here "+sendData);
res.send(sendData);
});
});
});


I also tried defining callback in the function itself, but gave error.

async.forEachOf(allDatabases, function(value, key, callback() {
^


SyntaxError: Unexpected token (
at exports.runInThisContext (vm.js:53:16)

Answer

forEachOf(obj, iterator, [callback]) So, try to change code like below

                console.log("There "+sendData);
            });
        } // end of "if(dbName!='local')"
    }, function(err) {
        console.log("Here "+sendData);
        res.send(sendData);
    });

If result.databases is Array then more suitably use map

app.get('/tasks', function (req, res) {
    var connection = mongoose.createConnection('mongodb://localhost/temp');
    connection.on('open', function() {
        new Admin(connection.db).listDatabases(function(err, result) {
            console.log('listDatabases succeeded');
            // database list stored in result.databases 
            var dbs = result.databases
                .map(function(db) { return db.name}) // transform to ['db1', 'db2', 'local']
                .filter(function(name) { name != 'local' }); // remove 'local'

            async.map(dbs, function(db, callback) {
                var conn = mongoose.createConnection('mongodb://localhost/' + db);
                var Meta = new mongoose.Schema({
                    originalname : { type: String, trim: true }
                });
                conn.model('meta', Meta).find({ task: { $ne: null } }, function(err, doc) {
                    // probably we need close temporary conn; I don't work with mongodb
                    // If we don't need to close then we call callback instead function(err, doc) and transfrom if finally-function
                    callback(err, (err) ? null : {
                        "task_hash" : db,
                        "task_info" : doc[0].toObject()
                    });
                }); 
            }, 
            // async finally function 
            function(err, results) {
                if (err)
                    return ...; // Show error to user

                console.log(results);
                res.json(results);
            }); // end of async  
        });
    }); // end of connection.on('open', ...
});