coding_hero
coding_hero

Reputation: 1769

I guess I don't "get" async programming

I've been using node.js for about 6 months now, off and on. But, I guess I still don't completely understand designing a program around asynchronous calls.

Take, for example, my most recent program, that needs to read a config, use that config to connect to the database, and then connect to every address in the database asynchronously.

I'm using the modules fnoc and node-mysql, but this is just pseudocode.

// first, get the config
fnoc(function(err, confs){
   // code stuff in here

   //now check that there's a database config
   if (confs.hasOwnProperty("database"))
   {
      // set up db connection
      var mysql_conn = mysql.createConnection({
          host:   confs.database.host,
          user:   confs.database.user,
          password:       confs.database.password,
          database:       confs.database.database
      });
      // do some querying here.
      mysql_conn.query(query, function(err, records, fields){
          records.forEach(function(host){
              // four levels in, and just now starting the device connections
          });
      });


   }
});

Every time I write something like this with callback inside of callback inside of callback, I feel like I'm doing something wrong. I know of promises and the async node library, but it seems like if those are the solutions, they should be default functionality. Am I doing something wrong, or is it just not clicking for me?

EDIT: Some suggestions include using functions for the callbacks, but that seems worse somehow (unless I'm doing it wrong, which is entirely possible). You end up calling one function inside of another, and it seems especially spaghetti-ish.

The example above, with functions:

function make_connection (hosts) {
hosts.foreach(function(host){
      //here's where the fun starts
    };
}


function query_db(dbinfo){
    var mysql_conn = mysql.createConnection({
          host:  dbinfo.host,
          user:  dbinfo.user,
          password:       dbinfo.password,
          database:       dbinfo.database
    });

// do some querying here.
    mysql_conn.query(query, function(err, records, fields){
    make_connection(records);
});

}



// first, get the config
fnoc(function(err, confs){
   // code stuff in here

   //now check that there's a database config
   if (confs.hasOwnProperty("database"))
   {
      // set up db connection

      query_db(confs.database);
      var mysql_conn = mysql.createConnection({
          host:   confs.database.host,
          user:   confs.database.user,
          password:       confs.database.password,
          database:       confs.database.database
      });
      // do some querying here.
      mysql_conn.query(query, function(err, records, fields){
          records.forEach(function(host){
              // four levels in, and just now starting the device connections
          });
      });


   }
});

Upvotes: 2

Views: 164

Answers (3)

durum
durum

Reputation: 3404

If you feel really tired of endless callbacks, try Q or co. You can write node.js code like this:

co(function *(){
  var a = get('http://google.com');
  var b = get('http://yahoo.com');
  var c = get('http://cloudup.com');
  var res = yield [a, b, c];
  console.log(res);
})()

It's almost a different way of writing, so it can be difficult to grasp but the results are quite good.

Upvotes: 0

TastySpaceApple
TastySpaceApple

Reputation: 3185

The aim of asynchronous functions and callbacks is to avoid any conflicts (which can happen more than you think!) between objects.

I'd like to point you to this asynch enthusiast: http://www.sebastianseilund.com/nodejs-async-in-practice

Yes, the callbacks do take some getting use to, but it's worth it!

Upvotes: 1

Ingo Bürk
Ingo Bürk

Reputation: 20033

In short words: instead of

foo(function () {
    // ... stuff #1 ...

    bar(function () {
        // ... stuff #2 ...

        baz();
    });
});

do

foo(handleFoo);

function handleFoo() {
    // ... stuff #1 ...

    bar(handleBar);
}

function handleBar() {
    // ... stuff #2 ...

    baz();
}

Of course, it can (and maybe should) be more granular, but that depends on the actual code. This is just a pattern to avoid nesting functions. You can also encapulsate these methods more.

This is the "vanilla" approach. There are also libraries that allow you managing this in nice ways.

Upvotes: 0

Related Questions