Reputation: 1769
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
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
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
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