Friday, May 11, 2012

Time To Consider Node.js?

Unless you’ve been living under a rock for the past couple of years, you’ll have heard the buzz about Node.js, a platform for building network applications in Javascript. If, like me, you’re a .NET developer working on Windows, you’ll have thought, ‘that’s nice, now back to work’. But I think it’s now time to consider adopting Node as a core part of our toolkit. It allows us to do some things far easier than we can with our existing tools, and it’s now mature enough on Windows that you don’t have to jump through hoops in order to use it. There’s a very nice IIS integration story now with iisnode.

Here’s a little example. I needed to write a little web service that simply waited for a second before responding. I wanted a harness to test the asynchronous IO handling in EasyNetQ. I’d written something to do this in .NET previously. Here’s my IHttpHandler implementation…

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace TestHttpHandler
{
public class TimerHandler : IHttpAsyncHandler
{
public void ProcessRequest(HttpContext context)
{
throw new InvalidOperationException("This handler cannot be called synchronously");
}

public bool IsReusable
{
get { return false; }
}

public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback callback, object state)
{
var taskCompletionSouce = new TaskCompletionSource<bool>(state);
var task = taskCompletionSouce.Task;

var timer = new Timer(timerState =>
{
context.Response.Write("OK");
callback(task);
taskCompletionSouce.SetResult(true);
});
timer.Change(1000, Timeout.Infinite);

return task;
}

public void EndProcessRequest(IAsyncResult result)
{
// nothing to do
}
}
}

It’s not trivial to write a non-blocking server like this. You have to have a good handle on the TPL and APM, something that’s beyond many mid-level .NET developers. In order to run this on a server I have to set up a new Web Application in IIS and configure the Web.config file. OK, it’s not a huge amount of work, but it’s still friction for a small throw-away experiment.
 
Here’s the same thing in Node:
var http = require('http');

http.createServer(function (req, res) {
setTimeout(function () {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('OK');
}, 1000);
}).listen(1338);

console.log('LongRunningServer is at http://localhost:1338/');

First of all, it’s less lines of  code. Node is asynchronous out of the box, you don’t have to understand anything more than standard Javascript programming idioms in order to write this service. I’m a total Node novice, but I was able to put this together far faster than the .NET example above.

But the runtime story is very nice too. Once I’ve installed Node (which is now just a question of running the Windows installer) all I have to do is open a command prompt and write:

node LongRunningServer.js

I don’t think I’m going to abandon .NET just yet, but I do think that I’ll be considering Node solutions as an integral part of my .NET applications.

9 comments:

Iain Partington said...

Mike,

Just for you info, as part of .net 4.5, the new Await and Task API, you are able to do public aysnc void() { Await Task.Wait(1000); }}

Maybe something you may want to consider.

Cheers

Iain

Jake Scott said...

using System.Diagnostics;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web.Http;

namespace MvcApplication2.Controllers
{
public class ValuesController : ApiController
{
public async Task> Get()
{
Debug.Write("GET /api/values/");
await TaskEx.Delay(1000);
Debug.Write("GET /api/values/ DONE");
return new HttpResponseMessage("ok", new MediaTypeHeaderValue("text/html"));
}
}
}

Ed Blackburn said...

Food for thought regardless of C#5

If we can xcopy deploy a node server too, then, well now we're talking...

Nick said...

Node may have many killer features - I don't know.

This is poor example of why a .NET dev should consider it, though, imo.

Give me more reasons and I'll happily listen.

Jason Wyglendowski said...

Mike how about security? I have been looking for a good example but have not found one on the windows stack. I assume since it's offered on Azure that there must be one. If you come across one would you consider doing a post on the subject? Thanks...

Anonymous said...

Actually, node.js has _no_ killer features. Jake Scrott shows in the comments how to to this with C# 5. The handler example was contrived to make C# come out as bad as possible.

Considering the C# 5 example, what more does node offer? Nothing. But a lot less in other places.

It is nearly worthless. I can't think of any production project at all where I'd use it.

Rohit said...

Also read http://teddziuba.com/2011/10/node-js-is-cancer.html

Mike Hadlow said...

Iain, Jake, Great 4.5 examples.

EJB, yes, that's a killer feature.

Rohit, great link, I hadn't seen that.

NTCoding, sorry for the poor example. Check out the Node website there's a load of interesting stuff there.

Anonymous, you're implying that I'm more intelligent than is actually the case. Oh that I was brainy enough to actually 'contrive' a bad example ;)

Thanks for the great comments guys.

Chris Marisic said...

Code rant is a good title, this is a rant more than anything. Node.js is new and built entirely around async up front, so does it have a better async story at this minute? Probably.

Will it have a better async story than .NET 4.5 come November? Absolutely not.

Also the software stack of ASP.NET has been matured over nearly a decade now. Sure there's still some aberrations in it (mostly from Micrsoft's fear of breaking changes) like membership, but there's huge extensibility to improve upon areas even if they're legacy.

Show me how you would achieve the aspect orientated programming that the ASP.NET MVC pipeline provides in Node.js. I guarantee you it will not be like [MyActionFilter] and magic ensues.