Web development with Node.js just rocks.
Okay, Node.js rocks. Especially with socket.io . As far as I'm concerned, this is web development where you have a huge amount of control. Your server can be used to its max capacity (on a one core machine, at least, otherwise you still need to run nginx to do load balancing between the cores, for now), and your entire app is compiled to machine code. No matter how many requests you get, you just have one instance running, no worrying about threads in your server code.

This is insanely great for writing the controller layer of MVC. The rest of your stack can be implemented as asynchronous communication with the controller -- I/O to the internet, I/O to the filesystem, I/O to the database, etc. They can be implemented with queues, or whatever else you want. And each can be load-balanced and/or sharded if necessary. Scalability made simpler! :)

People who say that Node.js is not "truly" asynchronous because there is only one thread for your javascript ... to you I say, so what? The point is, your controller process is not wasting any time! Which is more than I can say for PHP, Ruby, et al.

Having one thread is great for web servers, and it gives you a very clear analysis of your program. And if this is the way things will go, then you can truly write websites with just Javascript + HTML. It's funny how for many years Google wrote everything in Java and translated it into javascript, but now you can just write everything in Javascript.

That said, I immediately encountered an issue where you want to have more expressiveness with all this new "asynchronous" power you are given. For example:

a) You want to wait until you fill a few variables like "user" and "stream", and only then proceed to do something with them

b) You want to send a few queries to the database, and only once they all return, do you want to execute a callback

c) You want to wait until some resource is available, and only then use it

All are variations on the same common theme: conditional callbacks. So here is a function that I wrote to handle all that for myself. Hopefully it'll help those of you using Javascript and maybe some of you can improve on it:

/*
* Creates a callback to be called after multiple functions are done
* Usage:
* var wait = Pie.wait(function (params, subjects) {
* // arguments that were passed are in params.user, params.stream
* // this objects that were passed are in subjects.user, subjects.stream
* }, ['user', 'stream]);
* mysql("SELECT * FROM user WHERE user_id = 2", wait.fill('user'));
* mysql("SELECT * FROM stream WHERE publisher_id = 2", wait.fill('stream'));
*
* @param callback Function
* The callback to invoke when everything is ready. It is passed
* an array or object, depending on whether the "required" field was
* a number or array, respectively.
* @param required Array
* Pass an array of required field names here.
* @param defaultReturn
* Defaults to undefined. The value to return if callback is not yet ready.
* @return Object
* An object with the following method: fill(field).
* Call this method to return a callback.
*/
me.wait = function(callback, required, defaultReturn) {
if (typeof required === 'array') {
var len = required.length;
var result = {
callback: callback,
params: {},
subjects: {},
fill: function(field) {
var t = this;
return function() {
t.params[field] = Array.prototype.slice.call(arguments);
t.subjects[field] = this;
t.check(field);
};
},
check: function (field, args) {
var i, k, found;
for (i=0; i<len; ++i) {
found=false;
for (k in this.params) {
if (k === required[i]) {
found=true;
break;
}
}
if (!found) {
return defaultReturn;
}
}
return this.callback.call(this, this.params, this.subjects);
}
};
return result;
}

};