Category > grokking-javascript

Root.js : A Skeletal MVC Framework for Node.js
Posted by postfuturist on 2009-12-04 21:47:49

OK, by skeletal, I mean absolutely no fat whatsoever. What you are about to witness is merely an illustration of a thought. Here's the thought: I want to do serious server-side web development with JavaScript and Node.js. Why? Node.js is a convergence. The creation of Node.js was precipitated by several phenomena including the rise of JavaScript as the central programming language of the web, increased interest in functional programming, and advances in event-based programming such as epoll system call in Linux 2.6.

Without further ado, here is Root.js in primordial form:

var sys = require("sys");
var http = require("http");
var posix = require("posix");

function loadfolder (name)
{
var data = {};
var output = sys.exec("ls " + name).wait();
var files = output[0].split("\n");
for(var j in files)
{
if(files[j].match(/\.js$/))
{
var modname = files[j].replace(/\.js$/, "");
sys.puts("Loading " + name + "/" + modname);
data[modname] = require("./" + name + "/" + modname);
}
}
return data;
}

var models = loadfolder("models");
var views = loadfolder("views");
var controllers = loadfolder("controllers");

for(var x in controllers)
{
controllers[x].load(models,views);
}

var routemap =
[
[/^\/other(.*)$/, "other"],
[/^\/(.*)$/, "default"]
];

http.createServer( function (request, response) {
for(var i in routemap)
{
var route = routemap[i];
var matches = route[0].exec(request.uri.path);
if(matches != null)
{
matched = true;
var c = controllers[route[1]];
c.handle(matches.slice(1),request,response);
return;
}
}
}).listen(8000);

sys.puts("Server running at http://127.0.0.1:8000/");


This file expects a few things. It expects there will be folders named models, views, and controllers. In its current configuration the routemap will expect to find files named default.js and other.js in the controllers folder. Any controllers should export a function called load that provides a way to pass in the models and views during initialization and a function called handle that is called when there is an incoming request. Here is a simple example controller (default.js):
var models = null;
var views = null;

exports.load = function (m,v) { models = m; views = v; };

exports.handle = function (matches, request, response)
{
models.mymodel.getData( function (data) {
views.defaultview.show(response,data);
});
}


This controller calls the getData function exported by the mymodel model which would be a file named mymodel.js in the models folder looking something like this:
var data = 
{
title : "Page Title",
message : "Hello, JS World"
};

exports.getData = function(callback)
{
callback(data);
}


In this case, the model does not need to do an asynchronous call to get the data, but in case it did, the controller passes in a callback that the model can pass the data to asynchronously, in typical Node.js fashion. The last thing we need is the view (views/defaultview.js):
var posix = require("posix");
var jsontemplate = require("../json-template").jsontemplate;
var templates = {};

loadtemplates = function()
{
templates['basic'] = jsontemplate.Template(
posix.cat("./templates/basic.html").wait());
}

exports.show = function(response, data)
{
response.sendHeader(200, {"Content-Type":"text/html"});
var text = templates['basic'].expand(data);
response.sendBody(text);
response.finish();
}

loadtemplates();


Oh yes, and the template (templates/basic.html):


{title}


{message}



This example uses JSON Template which I briefly discussed here.

The preceding code actually works. It's missing the controllers/other.js controller, but it's enough to get the general idea. I could sit down with this as a starting point and create a web application. In fact, I just may do this. This framework has basically zero helper functions. I've noticed that the best helper functions and other abstractions of useful functionality spring forth naturally from the act of programming and active refactoring. When I notice myself repeating work, or pondering the idea of copy-pasting code from one part of an application to another, that's generally the time I do the work of building infrastructure. If I decide to use this framework to do something useful, then it will develop naturally. Right now it is a blank canvas.

I recently used Redis to solve some problems as work. There is already a node.js library for accessing Redis here, so I'm thinking about building something with that. Redis is essentially a persistent key-value store that supports simple data structures with atomic operations such as lists and sets. The "list" solved a very specific problem for us which had previously been partially solved (in an ultimately broken way) by building a queue on top of Memcached using a locking system built on the atomic increment and decrement operations. We dropped in the Redis list and everything started working perfectly.

If I decide that I need a traditional SQL backend, I would probably use DBSlayer, a http/JSON interface for MySQL, though Ryan Dahl has promised native support for some traditional databases in future versions of Node.js. Cool.

Node.js and JSON Template : A delicious pairing
Posted by postfuturist on 2009-11-26 01:26:57

I recently blogged about the virtues of Node.js and my personal desire to use JavaScript on the server. Well, I decided to start putting the pieces together. First of all, every good web framework needs a template system. I found JSON Template, a simple enough template system written in JavaScript and intended for client-side HTML template work.

I decided to combine the "Hello, World" examples from Node.js and JSON Template. This is what I came up with.

The first thing you have to do is make JSON Template conform to the CommonJS standard which Node.js so wisely implements. To do that, add the following line to the end of the json-template.js file:

exports.jsontemplate = jsontemplate;

That was easy enough. Put that file in the same folder as your Node.js project and include it with the following line:
var jsontemplate = require("./json-template").jsontemplate;

And now for the big finale, Node.js with JSON Template:
var sys = require("sys");
var http = require("http");
var jsontemplate = require("./json-template").jsontemplate;

http.createServer( function (request, response) {
response.sendHeader(200, {"Content-Type":"text/plain"});
var t = jsontemplate.Template('Hello {name}');
var text = t.expand({'name': 'world'});
response.sendBody(text);
response.finish();
}).listen(8000);

sys.puts("Server running at http://127.0.0.1:8000/");


Thanks to MV for referring me to CommonJS. He seems to have realized the power of an all JavaScript web development stack for some time and has some good rants on the topic.

An Apology For JavaScript
Posted by postfuturist on 2009-11-24 23:02:36

JavaScript is an excellent programming language. As a language, its strength lies in the simplicity and regularity of its syntax. I'm going to show you how much simpler it is than even Python or Ruby. OK, here is how you define a function in JavaScript:

function hello(target) {
alert("Hello, " + target);
}

And here is how you create an anonymous function:
function (target) {
alert("Hello, " + target);
}

There really aren't many surprises here. Basically, omit the name and you have an anonymous function object. The following is very similar to the first excerpt (not exactly, but close enough):
var hello = function (target) {
alert("Hello, " + target);
}

There are no arbitrary limitations or unwieldy syntax shifts in JavaScript surrounding named and anonymous functions. You can call a function with another one:
foobar( function() { do_something(); return 42; });

Python calls anonymous functions lambdas and gives them strange syntax and arbitrary limitations. Here is a normal Python function:
def hello(target):
print("Hello, " + target)

An anonymous function looks like this:
lambda target : "Hello, " + target

Oh, wait, it looks wierd and doesn't actually print anything. It only returns a string value. Yeah, that's Python's lambdas. There's been a lot of talk about it, and Python 3 has dumped them completely. Named functions are still first class objects in Python, so you can use those in most of the ways you would use an anonymous function, so JavaScript's calling a function with another function gets expanded a little in Python:
def thing:
do_something()
return 42
foobar(thing)

It is still elegant, just not as useful, IMO.
Ruby's named function:
def hello(target)
puts "Hello, " + target
end

Ruby's anonymous function:
proc { |target| 
print "Hello, " + target
}
# --OR--
Proc.new {|target|
print "Hello, " + target
}
# --OR--
lambda {|arg|
print arg
}

While the syntax may be... disconcerting, Ruby anonymous functions are just as powerful as JavaScript's.

In my day job, I write code mostly in PHP. The common PHP installation on a given server these days is PHP 5.2. This language is severely lacking. It does not have first class functions, though it is dynamic. It has classes, but they were strangely modeled after Java, a statically typed language. It is a sad little language deployed just about everywhere. In my daily work I bounce between JavaScript and PHP. Since the advent of V8, Google's insanely fast JavaScript implementation, I have thought it would be fun to use JavaScript on the server side. You get all the power and flexibility of a dynamic language, running several times faster than Python and Ruby with the ability to share code between server and client-side. My dreams have come true in the form of Node.js.

Now I know that server-side JavaScript has been around for a long time, it just hasn't seemed appealing for a number of reasons. First of all, I've only been doing professional web development for about a year, and I've only learned to appreciate JavaScript during that time. Secondly, early server-side JavaScript was in the form of ASP + JScript running under IIS. A crappy JavaScript implementation running on a closed Microsoft web stack is not my idea of appealing.

I've dabbled with using the "better" languages on the server side such as Python (Django and Pylons), Ruby on Rails, and Perl (Catalyst and CGI.pm). The distinct advantage is that these languages have large libraries and communities with vast quantities of pre-written code available with liberal, open source licensing. The frameworks are also mature and powerful. However, this does not exist for PHP. There are some libraries and code fragments available but the community surrounding PHP kind of sucks. The reason for this is that good programmers hate the language and don't want to waste time building things in it for free. Instead, they build things in Ruby, Python, and Perl.

The advantage of using JavaScript on the server is the easier context switching between client and server code. With JSON as the communication layer, there is no impedance mismatch between your server and client. Data can flow freely in both directions. Anonymous data structures in JavaScript are extremely powerful. They exist in Python, Ruby, and Perl, but the syntax is a little different and there are some gotchas here and there. Using JavaScript on the server and JSON as the data transport, you get a homogeneous stack. I hate writing a bunch of code and then watching it fail miserably because I was using the wrong operator to concatenate strings or constructing anonymous list with the wrong delimiters.

Programming fluently is like speaking fluently, it takes a lot of time with a single language to get the point where you don't have to stop and look things up all the time. The time it takes to look up how to do X in language Y is a real productivity killer. Sure, you are learning, but it's something that you've already learned in a bunch of other languages, it's just that you haven't done it enough in this particular language. Or each language does it very slightly differently, so you get them confused over time. In the world of hobbyist programming, all the different language quirks are fun diversions, and you can ponder the benefits of this or that language feature or syntax or library API. But when you need to get things done for a client, they add up to annoyances. If I could just get and stay fluent in JavaScript and work with a complete JavaScript stack for web development, I think I could be very productive.

In time the JavaScript server-side frameworks and libraries will be built up and it will be a good thing.

Grokking JavaScript Part 3 : Functions
Posted by postfuturist on 2009-08-20 01:16:26

In JavaScript functions are also objects, just like arrays are also objects. Functions, when treated like objects, act like objects. They exist as instances and are referenced from variable names or object properties which are also just references. Here is a simple, empty function assigned to a variable (reference).

var emptyfunc = function() {};

Now, this function doesn't do much, but it is a full-blown instance of an object, and can have property values assigned to it.
var myfunc = function() {};
myfunc.foo = "bar";
myfunc["baz"] = "boz";

There is a shorthand for creating a function instance that looks more like C-style function definitions. It may look like a C-style function, but it is a named reference to a nameless function object, just like the previous examples.
var adder1 = function(a,b) { return a + b; );
function adder2(a,b) { return a + b; }; // identical to adder1

What separates functions from normal objects is that they may be called, as functions, and not just treated as objects. They may be called in two different ways. The first way is as a normal function that you might use in any language, with named formal parameters, return values and such.
var adder = function(a,b) { return a + b; };
var mynum = adder(2,2);
document.write(mynum); // 4

JavaScript functions have something special about their "object" part, it is not initialized as an empty object, but with a single property "prototype" which references a (usually) empty object.
var adder = function(a,b) { return a+b; };
document.write(typeof(adder)); // function
document.write(typeof(adder.prototype)); // object

The prototype property on the function exists to facilitate prototypical inheritance when the function is used to create an object (the second way it can be called). I'll explain what prototype does later. This second way of calling the function uses the "new" keyword and instead of returning a normal value (or null when there is no return statement reached) it returns a new object. The new object may be referenced in the function itself as "this".
var creator = function()
{
this.foo = "bar";
}
var newobj = new creator();
document.write(newobj.foo); // bar

This type of function is referred to as a constructor function. There is nothing different about a constructor function. One function can do both tasks, but this is rarely useful, as a constructor function called normally (without the "new" keyword) would not have a new object reference "this" to deal with, but would be messing with the "this" object in the surrounding scope. Since there are two syntaxes to create functions, one way of differentiating the functions is to use one syntax for normal functions, and the other for constructors. YMMV.
// assignment syntax for normal functions
var normalfunc = function()
{
return "hello";
}

// function definition syntax for constructors
function constructorfunc(a)
{
this.value = a;
}
var phrase = normalfunc();
document.write(phrase); // hello
var myobj = new constructorfunc(phrase);
document.write(myobj.value); // hello


These constructor functions are similar to class definitions, and indeed some JavaScript references are so bold as to call them classes. They are not. They are only functions (objects) which create other objects. If you haven't guessed it yet, the prototype property of the function serves as a prototype for the objects it creates (or so it appears). The constructor functions above have prototypes that are empty objects (default), so the "this" object created in the function starts out as an empty object that inherits the properties of the constructor's prototype.
function ABC()
{
this.normalvalue = "1";
}
// add a property to the prototype object
ABC.prototype.protovalue = "2";
// initialize new object from ABC constructor
var abc = new ABC();
document.write(abc.normalvalue); // 1
document.write(abc.protovalue); // 2

When you go to access a property of an object, the runtime first looks at the object, and if it can't find the property, it goes to the prototype of the object's constructor. So the object appears to be a clone, but is still secretly "borrowing" attributes from the constructor's prototype at the time of creation. Here is my proof.
function B() {};
B.prototype.foo = "bar";
var b = new B();
// change the foo property of b's constructor prototype
B.prototype.foo = "baz";
// and magically b appears to have changed too
document.write(b.foo) // baz

It gets trickier. If you assign a value to b's "foo" property, it creates a new "foo" property on the b object, so changes to the "foo" property of the prototype will no longer affect b.
function B() {};
B.prototype.foo = "bar";
var b = new B();
// add foo property to b object
b.foo = "hello";
// change the foo property of b's constructor prototype
B.prototype.foo = "baz";
// but that no longer affects b, as b has it's own foo
// property and no longer needs to borrow it from
// the prototype
document.write(b.foo) // hello

All objects actually are created as though from a function object called Object. This means that you can monkey with the prototype used for all objects.
Object.prototype.what = "yikes";
var emptyobj = {};
document.write(emptyobj.what); // yikes

This can have dire consequences. It is probably a good idea to neither mess with Object's prototype or use the "for in" style of looping through an object's properties.
Object.prototype.leech = "hello";
var myobj = {a : "1", steak : "sauce"};
for(x in myobj)
{
document.write(x + " : " + myobj[x] + ", ");
} // a : 1, steak : sauce, leech : hello,

Please leave comments if you found this useful (or if you hated it). Stay tuned for more.

Grokking JavaScript Part 2 : Simple Arrays
Posted by postfuturist on 2009-08-18 23:55:57

An array in Javascript is a superset of an object that contains an ordered list of references. Here is the simplest Javascript array imaginable:

[]

The references in an array are not named, so creating an array of (references to) values and assigning that to a reference (variable) is easy.
var myarray = [1,2,"3","four"];

Arrays elements can be referenced through a square bracket syntax similar to the properties of an object are referenced. The difference is that the index is numerical, with the first reference in the array being the zeroth.
var anarray = ["foo","bar",1000];
document.write(anarray[0]); // foo
document.write(anarray[1]); // bar
document.write(anarray[2]); // 1000

Since arrays are also objects, named references may be added after creation.
var myarray = [1,2,3,"ABC"];
myarray.name = "MJ";
myarray["othername"] = "Michael";

There is no "literal" syntax to initialize a JavaScript array with object properties. Some web pages suggest iterating through an array with the "for(x in y)" syntax, but this is prone to bugs, as this iteration will iterate also through the object properties of an array.
var myarray = [1,2,3,"ABC"];
myarray.name = "MJ";
myarray.push("hey");

for(x in myarray)
{
document.write("(" + x + " -> " + myarray[x] + ") ");
}
// (0 -> 1) (1 -> 2) (2 -> 3) (3 -> ABC) (name -> MJ) (4 -> hey)
document.write(array.length); // 5


To just iterate through the array elements and not the properties, the traditional C style for loop works best:
for(var x = 0 ; x < myarray.length ; x++)
{
document.write("(" + x + " -> " + myarray[x] + ") ");
}
// (0 -> 1) (1 -> 2) (2 -> 3) (3 -> ABC) (4 -> hey)

As you can see from these examples, arrays have some built-in properties and functions, like "push()" to add items to the end of the array and "length" which returns the number of array elements (not object properties). These helper functions and properties do not exist in the array's object property map, they are just part of the language and the JavaScript runtime knows what to do. In addition to the push() function, there is a pop() function which removes the last item of the array and returns it. To add items to the front of an array, there is the unshift() function and to remove them from the front of the array, shift(). There are others. Here is a taste:
var test = ["a","b","c"];
test.push("d"); // ["a","b","c","d"]
var letter = test.pop(); // letter is "d" and test is back to original state
var first = test.shift(); // first is "a" and test is ["b","c"]
test.unshift("A"); // ["A","b","c"]
test.splice(1,1); // removed second element, so test is ["A","c"]
var large = concat(test, ["d","e"]); // large is ["A","b","d","e"]
var short = large.slice(1,2); // short is ["b","d"]
var desc = large.join("+"); // desc is a string : "A+b+d+e"

The functions all act on the array elements, not the object properties. Arrays can contain themselves, too.
var myarray = [3,2,1,"ABC"];
myarray.push(myarray);
print(myarray[4][4][4][4][0]); // 3

Like objects, arrays have a special Java-like syntax for initializing them in addition to the literal syntax in the previous examples.
var e = new Array();
e.push("first");
var another = new Array("first", "second"); // same as ["first","second"]

Grokking JavaScript Part 1 : Simple Objects
Posted by postfuturist on 2009-08-18 20:51:28

To understand JavaScript objects, you have to understand references. A variable in JavaScript is a reference to an object or a primitive value. Here is the declaration of a variable holding a numerical value:

var foo = 9;

JavaScript objects are very simple. Here is the simplest JavaScript object imaginable:
{}

JavaScript objects are maps, which is to say a collection of mappings of names to references. Here is an object which has a few named references:
{ somenumber : 99, somestring : "ninetynine"}

Usually an object is assigned to a variable (reference) so it can be referred to later.
var myobj = {foo : "bar"};

The mappings are sometimes referred to as properties. They may be accessed from a reference to an object using the dot (.) syntax or the bracket syntax.
var myobj = {mynum : 9};
document.write(myobj.mynum)); // 9
document.write(myobj["mynum"]); // 9

JavaScript objects can have properties added to them after being created.
var myobj = {foo : "something"};
myobj.bar = "hey";
myobj["baz"] = 100;
var similarobj = {foo : "something",bar : "hey",baz : 100};

There is another syntax for creating an empty object. It is related to the Java-like syntax that JavaScript uses to create objects with prototype-based inheritance (which will be explained later).
var myobj = new Object();
myobj.blah = "100";
var identical = {blah : "100"};

Since the properties of an object are references, they may refer to other objects or to the object itself, recursively.
var complexobj = {innerobj : {prop : 100}, other : 9};
document.write(complexobj.innerobj.prop); // 100
complexobj.self = complexobj;
document.write(complexobj.self.self.self.innerobj.prop); // 100

Got it?