Hallo Matthew,

sorry for the late reply.

On Mon, Apr 9, 2012 at 2:42 AM, Matthew Hazlett <[email protected]> wrote:
> I'm trying to write a simple app that preforms a db query when a user
> connects to a tcp port.
>
> I can get the query working if I do everything as callbacks:
>
>    db.open(... fn() {
>        db.collection(.... fn() {
>             db.query(...... fn() {
>             });
>         });
>     });
>
> But as you can see this creates callback hell.

Use the async-lib to make it flat (npm install async)

async.waterfall([
  db.open.bind(db, host, port, user, pass),
  db.collection.bind(db, 'select * from foos'),
  function(rows, cb) {
    var fn = function(row, cb) {
      db.query('select * from bars where barid='+row.barid, cb);
    };
    async.map(rows, fn, function(err, bars) {
      rows.forEach(function(row, index) {
        rows[index].bar = bars[index];
      }
      cb(null, rows);
    });
  }
], function(err, rows) {
  console.log(rows);
});

Using the async library has the nice effect to learn all
important async patterns. Later on you will not use the async-lib
that much, but there are sitiations where it is handy.

BTW: .bind is available on all functions.

> What I would like to do is have a class, but being as everything is async it
> makes it incredibly difficult to ensure all your variables are set.
>
> var client;
> db.connect(connect, fn(){
>     client = connect;
> });
> client.close();
>
> Will cause an error because client hasn't been set yet.

You have to make sure that the constructor of the class is also
async. It must either call a callback or fire an event to know
when the constuctor is ready:

function MyClass(db, cb) {
  var self = this; // dont loose the scope
  this.client = null;
  db.connect(function(err, client) {
    if(err) {
      this.emit('error', err);
      return cb&&cb(err);
    }
    self.client = client;
    self.emit('connected', client);
    cb&&cb(null, client);
  });
}
require('util').inherits(MyClass, require('events').EventEmitter);

var myobj = new MyClass(db, function(err, client) {
  myobj.client.close();
});

myobj.on('error', function(err) {
  console.log(err.stack||err);
});

myobj.on('connected', function(client) {
  myobj.client.close();
});

> Another thing I
> thought of doing was chaining it all together:
>
> db.connect(connect, fn(){
>    ...
>   process.nextTick(fn(){ doNext(); });
> });

I do not understand what you want to do here.

> this gets very messy and hard to manage, how can I deal with callback hell?

It takes some time to get used to it, but it is not rocket
science.

I hope this helps.

-- 
Job Board: http://jobs.nodejs.org/
Posting guidelines: 
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

Reply via email to