4

I'm learning node.js coming from a PHP background with a limited JavaScript level. I think I got over now the change of mindset implied by the asynchronous approach. And I love it.

But, as many others before me, I quickly understood the concrete meaning of the "pyramid of doom".

So I build these little 'dummy' route and view to understand how to properly use Async.js. I just spend the last 5 hours writing the following code (rewritten of course tens of times). It works, but I wonder how I could go further and made this code more simple (less verbose, easier to read and maintain).

I found many resources on the web and especially here, but always by bits of info here and there.

I'm guessing at this point that I should use "bind" and "this" with async.apply to make to shorten the 2 last functions called by the waterfall.

The issue is to get the object "db" defined so I can use the "collection" method on it (for the second function).

I really searched an example in Google, but it's surprising that you don't get straightforward examples looking for "async waterfall bind" (as well as many keyword variations I tried). There are answers of course but none seems relevant to this particular issue... ore, quite possibly, I haven't understood them.

Can someone help me on this? I'll be quite grateful.

app.get('/dummy',

    function(req, res) {

        var MongoClient = require('mongodb').MongoClient;

        async.waterfall(
            [
                async.apply(MongoClient.connect, 'mongodb://localhost:27017/mybdd'),

                function(db, callback) {
                    db.collection('myCollection', callback);
                },

                function(collection, callback) {
                    collection.find().sort({"key":-1}).limit(10).toArray(callback);
                }

            ], function(err, results) {
                if (err) console.log('Error :', err);
                else { res.render('dummy.jade', { title:'dummy', results: results} ); }
            }
        );

    }

);
  • Can you post what you want the code to look like? – mak Jul 13 '13 at 08:36
  • Ideally, the second and third functions would be 1 line only, e.g. without going through anonymous functions. It _seems_ possible according to my readings on StackOverflow and the web, using "bind" and "this"... but I haven't been successful yet. –  Jul 13 '13 at 08:48
  • 1
    I don't think it's possible, since `bind` assumes that you have an function/method to bind, and the objects which contain the methods in this case (`db` and `collection`) are dynamic results of a previous step in your waterfall. – robertklep Jul 13 '13 at 13:08
  • 1
    ok, I took me some time to understand your answer but I think you're right. This works anyway, but if someone has an idea the more even more concise using whatever need, I'm interested to know, for the sake of always keeping learning! ;-) Thanks, robertklep and @mak for your attention to my question. –  Jul 14 '13 at 22:54
  • Remember that the first argument, of bind, is the context of the call: http://stackoverflow.com/questions/22714355/async-apply-inside-async-waterfall – sergolius Oct 08 '15 at 07:37

2 Answers2

1

If you're using the mongodb JS Driver, then this should work:

async.waterfall(
            [ 
             function (cb) {
               new MongoClient(...)
               .connect('mongodb://localhost:27017/mybdd', cb);
             },

             function (db, callback) {
               db.collection('myCollection', callback);
             },
...

Alternatively, if you want to use async.apply, just pass an instance of MongoClient

async.apply(new MongoClient(...).connect, 'mongodb://localhost:27017/mybdd')
Mrchief
  • 75,126
  • 20
  • 142
  • 189
0

I've recently created a simple abstraction named WaitFor to call async functions in sync mode (based on Fibers): https://github.com/luciotato/waitfor

I'm not familiar with mongodb client, so i'll be mostly guessing what you're trying to do:

using WaitFor your code will be:

var MongoClient = require('mongodb').MongoClient;
var wait = require('waitfor');

app.get('/dummy', function(req, res) { 

       // handle request in a Fiber, keep node spinning
       wait.launchFiber(handleDummy,req,res) 

       }
);


function handleDummy(req, res) {
    try {
        var db = wait.for(MongoClient.connect, 'mongodb://localhost:27017/mybdd');
        var collection = wait.forMethod(db,'collection','myCollection');
        var results = wait.forMethod(collection.,'sort',{"key":-1}).toArray();
        res.render('dummy.jade', { title:'dummy', results: results} );
    }
    catch(err) {
        res.render('error.jade', { title:'error', message: err.message} );
    }
};
Lucio M. Tato
  • 5,639
  • 2
  • 31
  • 30