Experimenting With Node.js And Server-Side Javascript

Over the past few years, Javascript has gone from being a misunderstood, ill-perceived language to being probably one of the most important languages in existence. It is, quite literally, the language that powers the interent; or rather, the Web 2.0 version of the internet. And now that it has gained so much popularity on the client-side, people are bringing it server-side in order to create extremely fast, non-blocking, event-driven application architectures. Admittedly, I don't know very much about server-side Javascript; so, I wanted to take some time to play with Node.js - the apparent front-runner in server-side Javascript technology.

To get my feet wet, I followed one of the many "Getting Started With Node.js" tutorials. One common theme to all of these tutorials is the creation of an HTTP sever with just a few lines of Javascript code. I have to say, it is pretty freaking cool! But, since setting up the HTTP server is so easy, I wanted to try and take it one step further and create the most basic of RESTful API interfaces.

For this demo, I have set up a RESTful API that provides access to a "Girls" collection. The URLs that I am using are not truly "RESTful"; but, they get the job done and get the point across. Here are the available URLs:

/girls/get/

/girls/{id}/get

/girls/{id}/delete

/girls/add/{name}

Of course, in the above URLs, {id} and {name} would be replaced with meaningful domain data.

Node.js provides a module architecture; but, I don't really know anything about it just yet (and I certainly don't want to spread any misinformation). So, for my experimental purposes, I have just kept all of the code in a single file - sorry for the mess. The first bit of code sets up the HTTP server and defines the RESTful URL parsing. The second bit of code defines the service layer for the Girls collection:

// Include the necessary modules.

var sys = require( "sys" );

var http = require( "http" );

// ---------------------------------------------------------- //

// ---------------------------------------------------------- //

// Create an instance of the HTTP server.

var server = http.createServer(

function( request, response ){

// We are going to be looking at urls for RESTful commands.

// These will be in the form of:

//

// girls/get

// girls/{id}/get

// girls/{id}/delete

// girls/add/{name}

// Set our default response.

var apiResponse = null;

// Define our patterns.

var patterns = {

getAll: new RegExp( "girls/get", "i" ),

getGirl: new RegExp( "girls/(\\d+)/get", "i" ),

deleteGirl: new RegExp( "girls/(\\d+)/delete", "i" ),

addGirl: new RegExp( "girls/add/([^/]+)", "i" )

};

// Strip off the leading and trailing slashes.

var restUri = request.url.replace(

new RegExp( "^/|/$", "g" ),

""

);

// Loop over the patterns to see if any match.

for (patternKey in patterns){

// Try to match the pattern against the URL.

if ( match = restUri.match( patterns[ patternKey ] ) ){

// Pass the request off to the service layer.

apiResponse = girlService[ patternKey ](

match[ 1 ]

);

// The RESTful URL can only match one pattern.

// Since we found a match, break out of the loop.

break;

}

}

// For our demo puproses, our API will always return a valid

// response if the API request was successful. Otherwise,

// something could not be found.

if (apiResponse){

// Set the 200-OK header.

response.sendHeader( 200 );

// Return the response from the API request.

response.write( JSON.stringify( apiResponse ) );

} else {

// Something went wrong.

response.sendHeader( 404 );

}

// Close the response.

response.close();

}

);

// Point the server to listen to the given port for incoming

// requests.

server.listen( 8080 );

// ---------------------------------------------------------- //

// ---------------------------------------------------------- //

// I am the service object (or Data Access Object or Gateway) that

// provides access to the girls collection.

var girlService = (function(){

// Create our collection of girls. This collection is keyed by

// the ID of the girl.

var girls = {};

// Keep a running auto-incrementer.

var primaryKey = 0;

// Define our service object.

var service = {

// I add a girl to the collection.

addGirl: function( name ){

// Create the new girl instance.

var girl = {

id: ++primaryKey,

name: name

};

// Add it to the collection.

girls[ girl.id ] = girl;

// Return the new girl instance.

return( girl );

},

// I delete the girl with the given ID.

deleteGirl: function( id ){

// Get the girl.

var girl = this.getGirl( id );

// If the girl exists, delete her.

if (girl){

delete girls[ girl.id ];

}

// Return the girl.

return( girl );

},

// I return the girl with the given id.

getGirl: function( id ){

return( girls[ id ] || null);

},

// I get all the girls.

getAll: function(){

var orderedGirls = [];

// Loop over the primary keys to build up the collection

// of ordered girls.

for ( var i = 1 ; i <= primaryKey ; i++ ){

// Check to see if a girl exists at this key.

if (girls[ i ]){

// Add this girl to the result in order.

orderedGirls.push( girls[ i ] );

}

}

// Return the sorted collection.

return( orderedGirls );

}

};

// Return the initialized service object.

return( service );

})();

// ---------------------------------------------------------- //

// ---------------------------------------------------------- //

// Write debugging information to the console to indicate that

// the server has been configured and is up and running.

sys.puts( "Server is running on 8080" );

As you can see, the event listener for the HTTP server (remember Node.js is all about events!!) passes in a reference to the request and response objects. Our event handler then writes to the response buffer based on the incoming URL.

My mental model of Node.js doesn't extend much beyond that at this point; so, I'll stop here and just say watch the video above to see this all in action.

Reader Comments

You will find that as you start to take on bigger challenges leveraging some of the tools that have been built around Node will be super helpful.

Because of the architecture of node middle ware tools like Connect (http://senchalabs.github.com/connect/) will be really helpful. For instance it already contains helpers for routing which you had to write on your own.

Then their is Express (http://expressjs.com) which builds on to connect to add even more functionality. The developer community around node is on fire. Node.conf is next month and the conference sold out in an hour.

Let me know if you have any questions as you dig into Node. Glad to see you branching out beyond CF :)

@Ben, except for some minor syntax differences, cfscript is gosh-darn close to being server-side JavaScript. My holy grail for that is a new syntax for that can act as a cfinclude where the target file is assumed to be in cfscript mode. Something like

(cfscript src="targetfile.js")

What do we need? Well, make window a synonym for the Variables scope. Get rid of that CF-only {key=value} syntax for structs. A cfcompatibility.js file that you can include on the browser to define ArrayLen(), StructNew(), ListToArray(), etc, for use in the JS context (easier to do than ArrayName.length in the CF context).

It would be great to be able to use the same data validation scripts on the browser and on the server. I'm just sayin...

And @MichaelLong, you could still "ask what about database?" with cfscript src attribute. But if database I/O was performed outside the browser/server agnostic script, you could have a browser script that does SQLLite and a cfinclude file that does ColdFusion database I/O. Both could pass stuff into and out of the browser/server agnostic script through global variables.

Oh cool - sorry I won't be there! Node.js looks cool but is so new to me. I'd like to poke around a bit before I look into any real 3rd party structure that it gives me a chance to learn how some of it all fits together.

When I wrote this post, I had Node.js version 0.2.4 running. I tried to update to 0.4.5. Uggg - that was a nightmare! I've been using Homebrew as my package installer and it took me forever to figure out that I hade to use "--force" in order to get it to acknowledge that the live Formula was different than the one I had locally:

brew install --force node

I'm still learning my way around installing things on the Mac that don't involve double-clicking :D

@WebManWalking,

Hmmm, DC's not so far away. Let's see what the next few weeks do for my interest in Node.

@Michael,

I've seen it talk to a database somewhere; but, the cool thing about it is that it is evented rather than blocking; so, you don't wait for the data to come back from the database - you let the database notify your event handler when the data is ready.

I'm still trying to wrap my head around it :D

@Dave,

I started playing with the require() stuff once I got myself upgrade to the latest version. It seems to load an singleton object into the given, local namespace. But, that's about as far as I've gotten so far.

Holy cow - the NowJS stuff looks insanely easy! I'll definitely be checking that stuff out. I think realtime interaction is awesome and key to the future of awesomeness :)

I've seen the Let's Make A Web App popup on Twitter but haven't taken the time to look into it yet. Thanks for the link. I want to try and start out as simple as possible, so hopefully he steps through it slowly.

@Michael We are trying to address the issues you describe with Akshell (http://www.akshell.com) by providing an Apple like experience to developers just starting out with server side JavaScript.

We have a very well defined, open set of core libraries (http://www.akshell.com/docs/0.3/ref/) and plan to provide some mechanisms that would allow for the more popular and stable open source libraries to rise to the top, so that developers do not need to know which of the many e.g. XML libraries to use.

Also, we have implemented our stack from the ground up, including our own web server, and have support for one click deployment on both our subdomain, which you get automagically, and your own top level domain.

Finally, Akshell uses synchronous I/O for most operations which is easier to work with and for beginners to grasp. The plan is to include Node as a component of our infrastructure to allow for pubsub type of operations with Web Sockets, Comet and long poll requests.

Thanks for the link to the free ebooks - that has already proved useful!

I am fascinated by these out-of-the-box hosting solutions. Coming from a ColdFusion world, it's a bit hard for me to wrap my head around it. I think a big part of the disconnect that I have is that when testing, I manually have to kick up node on the command line to start testing:

"node server.js"

... in whatever directory the test code is. I don't yet fully have an understanding in my head about how this stuff all stays running in a "production" environment.

The EC2 stuff looks very cool for playing (especially since there are some distros that are fully configured already). I read a blog post the other the day that was like, "Learn Node.js for $0.02 - No more excuses!". Definitely very cool.

Tomorrow, I'm gonna install NPM, see if I can get some other stuff working locally for more fun an profit!

@Ben - if you use a service like No.de or DotCloud the services automatically run your app.

In the case of No.de you push your local Git repo to the server using server.js as your default start script. The No.de service will restart the app. If it has errors it reverts to the last good repo version.

In the case of DotCloud you use their CLI tool to deploy. DotCloud looks great they have MongoDB and others in alpha.

Also I see they have had requests for CF - guess it would be Railo if they decide to support it.

@Ben: Tomorrow's Node.js presentation is apparently going to be too beginnerish. You're way ahead of the topics covered (installation and dissecting a small app). Moreover, 88 people have RSVP'd that they're coming, despite the fact that they're going to be holding it in a parking garage!!

I agree with this statement strongly: Over the past few years, Javascript has gone from being a misunderstood, ill-perceived language to being probably one of the most important languages in existence.. It is amazing how far people have come to realizing that, too, isn't it? I remember not too long ago working for a company that did not allow us to use javascript at all. And there was a time when a lot of programmers didn't use it, but you almost have to in order to keep up today! I absolutely hate working on sites where you have to code for users who turn the javascript off. I hate that. I would much rather work in an organization where you have somewhat at least a bit of control over whether the viewers do this or not. Oftentimes, I will just simply put a noscript tag in the page with a link redirecting the user to instructions on how to turn javascript on, with an explanation that you really can't view the page adequately without javascript turned on.

I think part of the reason that the popularity of javascript has grown so much over the past few years is the onset of jquery. Jquery makes it so much cleaner, less frustrating, and more fun to write javascript. It's rare that a programmer will sit down and just hack out raw code in just pure javascript without using Jquery at some point. I personally love the stuff. It has made my life so much easier as a programmer and my pages so much better and pop so much more. I no longer have to be an artist with a great eye for the aesthetic and knowledge to do that in order to have a semi-pleasing-to-the-eye page. I'll admit that at times, before jquery, it could be hard to make simple errors and miss something and spend loads of time searching for the simple error with raw javascript. But with jquery, it seems like quite a bit of that has been cut out. I really have been enjoying it, and I have been enjoying your blogs on it. Keep up the good work, Ben!

As for 88 people having RSVP'd, that shows you the level of interest in node.js.

@Anna,

"with jquery, it seems like quite a bit of that has been cut out". I wish there were a book or something that treated jQuery like it was a part of the JavaScript language. I know that for me, I will never use getElementById.

I'd like to learn JavaScript, but the even gooder parts. Don't tell me about getElementsByClassName because it has been supplanted by $('.

and I wish I knew how to write that book. I'd be much richer and able to retire and not have to work anymore. Then, I could lounge out on the beach and drink my non-alcoholic pina coladas all day and soak in some sunshine every day, and only work when it was fun for me to do so. ahhhhh...to have that kind of talent. :-) (I will interject that I am writing a fiction novel, but I am far from getting that done. Who knows if I ever will? But it wouldn't be written to the same crowd as the javascript/jQuery book, and I wouldn't even begin to know how to write a book like that. :-( )

After taking my Node.js class last weekend, I ended up playing with a service - Nodejitsu - which, as you say, takes care of so much of the deployment details for you. They actually give you a command-line tool for wicked simple deployment.

I believe they can also handle Git-based employment as well; but I haven't tried that yet.

@Atle,

Yeah, that seems to be one of the downsides to Node.js at this point - it's moving so fast that there's a new version out like every 2 weeks :) This is what finally made me understand how / why things like Node Package Manager (NPM) are so important and how they deploy release-based versions of various modules. It's pretty crazy stuff.

@WebManWalking,

I'll get down to DC one of these days; things are just a bit too hectic right now. I've been working on a presentation (unrelated to Node.js) and it's wearing me a bit thin. Looking forward to zoning out a bit :)

@Anna,

jQuery has been amazing! I've been doing Javascript for a long time, way before jQuery came out. BUT, the stuff I could do after jQuery was introduced is orders of magnitude better than what I could do before. I was taught Javsacript in college 11 years ago; and it was very awesome! But, the things I could do were kind of lame. Certainly, I couldn't do much of anything with events beyond onClick() handlers and I NEVER did any kind of animation!! jQuery has really helped me push myself to the next level.

@Phillip,

Ha ha, I know what you mean. Now that I use jQuery in most projects, I have sort of stopped learning about new selectors - I just assume that Sizzle will build them in for me so that I will seamlessly start to take advantage of them.

@Ben, I know what you mean! I could do some really cool stuff that I thought was really neat, but when it came to doing stuff that really REALLY impressed the clients, plus stuff that significantly added to the look and feel of the site, I wasn't really able to do any of that until Jquery came along. Strangely enough, I was a little wary of jquery at first, but once I got my feet wet with it, I loved it! :-)

Slashdot has a recent thread on Brendan Eich's recent attempts to influence the direction of JavaScript. The thread has turned into a total flamefest on JavaScript's ubiquity and how it's become, as you put it, "probably one of the most important languages in existence". I'm not sure if you want to add the weight of your knowledge to cool down the roaring flames, but here's the URL anyway, in case you want to at least read it:

Those kind of arguments are beyond me. I don't understand things at the philosophical level - I like to play around in the technical stuff and trying to figure out how stuff works. I'll leave the bigger debates up to the smarter people :)

All I know is that I really enjoy working with Javascript.

Plus, I think people take things too far. Like, just because there is server-side Javascript doesn't necessarily mean (in my opinion) that DOM-based templating is the best way to do things. I don't immediately see why the limitations of client-side templating should be placed on the server side.

If you do any HTML generation with ColdFusion, the idea of having to do DOM-based templating seems... absurd :) ColdFusion templating is childishly easy - CFLoop, CFOutput, etc. -- the language handles it with insane grace and ease. Just because you *can* do Javascript on the server doesn't mean that all client-side techniques need to be applied.

I've seen a lot of buzz about the 1.6 release but haven't had too much time to look into it in the last few weeks. Seems like they got that controversy fixed up with the attributes. I should definitely take some time to see what updates are available.

@Anna you're writing a novel, but a nice one! This article is about javascript but you have such a great talent to jump from one subject to another! Anyway, i would like to live that life that you're dreaming of! (Sorry for being not on topic Ben Nadel)

@Tim: I misread your comment at first and thought you were on to me! Most people do not consider that a talent, most consider it a disability...I think they call it either ADHD or ADD, depending on whether there is hyperactivity involved. Yes, I get off topic from time to time. But I agree that Jquery and Javascript is awesome, and by the way, here is a question that relates to anyone who would like to answer it on here that happens to be reading these comments: What do you do about your users turning off their javascript? I work for a company that requires their users to have javascript turned on, and as such, we use noscript tags and require users to turn on the javascript if they are to view the page and work on it in any reasonable way. But what do you do if you design/develop sites for the general public? Do you still do something to in some way require javascript? This is something I have been wrestling with for some time...

That's pretty cool. This stuff is definitely all the rage lately. I haven't played with in the past few weeks; I'm looking forward to diving back in a bit, especially now that I'm excited about playing with MVC-style apps in JavaScript again.

@Tim,

No worries at all. Anna brings a fresh perspective to things.

@Anna,

As far as JavaScript requirements, Barney Boisvert actually made a great point in his Progressive Enhancement talk at cf.Objective(). He made a good distinction between JavaScript as an "enhancement" vs. JavaScript as a "platform".

In the "Platform" camp, he groups things like Flex, Silverlight, and JavaScript RIAs (Rich Internet Applications). In this camp, it's all or nothing. Meaning, if you don't have the Flash plugin, your Flex app doesn't work. If you don't have the Silverlight plugin, your Silverlight app doesn't work. And, if you don't have JavaScript enabled, your JavaScript app doesn't work.

Those are platforms - they are engineered to depend on a known, working environment.

On the other hand, you have JavaScript as an enhancement. In such cases, you can/should build your entire site to work without JavaScript before you go back and start to add progressive enhancement features like AJAX-driven form submission and what not. With this kind of approach, you have to be careful to use appropriate HTTP standards for GET and POST (ex. you can never have a GET-link that performs a server-side delete since GET is not supposed to be augmentative).

So, at the end of the day, you have to decide if what you're building is a platform-dependent JavaScript applications or a plain site with JavaScript-based enhancements.

Of course, there are always special cases. Take my blog, for example; it's pretty much fully accessible without JavaScript. HOWEVER, a long time ago, I decided to make my Comment Form AJAX-only. I actually disabled the non-JavaScript version of it. I did this to specifically cut down on Spam form submissions. So, it's all in context.

Thanks, @Ben! I try to keep my comments on point, but my mind wonders from time to time. And thanks for all of your pointers about the javascript thing. That is a tough one. I have to admit, I love developing where I can control the environment. :-) I love jQuery. I love the things that it can do that make it completely dependent upon the user actually using javascript. But I have on occasion worked for design houses, and of course, they required the sites be accessible by nearly anyone on the internet. So I can do it. I just actually prefer jQuery being capable of being used. Not being able to use it, especially in all of the ways I have learned how...I feel so limited! :-/

Well, while you can't control the browser environment, at least jQuery goes a pretty long way to make sure we don't have to worry about the cross-browser differences too much. Not to get off topic, but I will probably never start another project without using jQuery. It's just awesome.

I agree with you totally, which is why I asked the question -- I really can't stand the thought of having to do another project without being able to use jQuery. The more I use of it, and the more stuff I see that it can do, the more I am sold on it. And I also appreciate the fact that we don't have to worry quite as much about cross-browser issues, though while on that topic, let me share a recent experience with you. I had this neat, cool little jQuery on a recent project I was doing, totally functional and all of that jazz...it looked so groovy and had a color scheme similar to your orange over here --> (matching our company's brand colors) When it came time for the thing to actually work and be tested, though, it worked in explorer and NOT in firefox. I realize some of you are laughing at the fact that I am bringing up explorer and that 'no real programmer' ever uses explorer, but in my defense, let me say that my company mandates their employees use explorer, so my stuff HAS to work in explorer, and if it works in firefox, that is just considered a bonus. Anyway...I finally, after many hours of working on it, came up with a solution to make it work in both. Was a lot of work that got me to that point, though. I coded quite a bit of it on my own, but admit that I got some of the code for it off the web somewhere. The code, as I grabbed it off the web, didn't work at all without some tweaking, and then, as I got it, it only worked in explorer. I added the hack to make it work in firefox, and now it works in both like a charm. At first, though, I thought I may get to the point to where I had to have it released just working in explorer :-/, because that is what is really important to my company, for the most part. I wish there was just something we could do, some code that we could write, that would just go into the client's computer and turn javascript on itself. ha! Do I sound like a nazi or what? No offense to any nazis out there reading this or anything...

Hi Ben,thanks for sharing such valuable and helpful info on Node.js : I wanted to ask you if you would be aware of any Training institutes or Training providers that impart trainings on Node.js in India.I am planning to get a training organized for some of our resources on this new technology.Would you be able to help me with the requested info.and once again, thanks for sharing your knowledge on the subject. Appreciate it.

Thank for sharing about node.js, but i would like to hear your opinion about what should i use in my new project. I have a client that need a chat system on his website for large group. His project will have maybe 1000000 users to use this chat. Before i was using Red5+java+flash+jquery and i it works great but i want to know what if u think if i will use node.js for chat? Do you have experience with node.js on large scale? As i see node.js looks really easy compare to what i used before ...

I am the co-founder and lead engineer at InVision App, Inc — the world's leading prototyping,
collaboration & workflow platform. I also rock out in JavaScript and ColdFusion 24x7 and I dream about
promise resolving asynchronously.