Getting Started with Pronto.js

Aug 27 2012

Pronto.js is a JavaScript library for application building. Designed for Node.js, it makes writing high performance asynchronous applications much easier. And it introduces modularity so that you can build applications with highly reusable components. ConsumerSearch.com (part of About.com, a New York Times company, etc.) uses Pronto to communicate with their mobile apps.

How Pronto Works

Pronto doesn't use the MVC (Model View Controller) pattern prominent in many applications. There are several reasons for this, but the big one is simple: MVC isn't a terribly good fit for Node.js. If you really like MVC, you can actually reproduce it conveniently in Pronto.js, but the framework itself doesn't make you use it.

Instead, Pronto combines two other patterns: Front Controller and Chain of Command.

  • Front Controller: This is basically the "router" part of most MVC implementations. In a nutshell, it sits at the front of the application and maps incoming requests to the code that can handle those requests.
  • Chain of Command: This pattern takes a particular request and executes a series of commands in response. Each command builds on the previous command, thus they act like a "chain".

A First Pronto Project

To get started with Pronto using Node.js, give this a try. What we are going to do is build a very simple "Hello World" application. This doesn't get into the details of working with a context or writing your own commands, but it will help you get started. <!--break-->

Get Ready

Create a new application directory. $ mkdir example-project

Change into that directory: $ cd example-project

Install Pronto

Now we need to create a new package.json file. This is used by npm (Node's package management tool) to learn about our app and install its dependencies. Mine looks like this:

{
  "name": "example-project",
  "description": "Simple example of Pronto.js",
  "version": "0.0.1",
  "author": "Matt Butcher <technosophos@gmail.com>",
  "contributors": [
    {"name": "Matt Butcher", "email": "technosophos@gmail.com"}
  ],
  "main": "index",
  "dependencies": {
    "pronto": ">=0.2"
  },
  "engines": {"node": ">= 0.4.9 < 1.0.0"}
}

The most important part of the above, for our purposes, is the dependencies section. In order to use Pronto, we want to have it listed there.

From here, we can just execute npm install to download and install Pronto.

A Simple Command Line Client

Now that we have that done, we can write a very simple command line client.

Here is the complete code for our simple command line client. I've stored it in a file called hello.js, which can be run by typing node hello.js.

/*!
 * A simple Hello World CLI.
 */

// Pronto itself.
var pronto = require('pronto');

// A testing command.
var Hello = pronto.commands.Hello;

// The registry. This defines all of the
// routes that the app knows about.
var registry = new pronto.Registry();

// The router is what runs commands.
var router = new pronto.Router(registry);

// Build a route.
registry.route('hello')
  .does(Hello)
  ;
// This is how we run a command. You could
// get this info from ARGV or some other
// source, but we hard code it here.
router.handleRequest('hello');

Running node hello.js should output the following:

info: Hello World

And then terminate.

How the Code Works

First, we import the pronto library with require('pronto').

Second, for convenience, we map Hello to pronto.commands.Hello. Pronto has several built in commands. This one is actually designed to help new developers get comfortable with Pronto.

After this, we build the two major Pronto pieces: A registry and a router.

The registry is where we map pronto route names to a chain of commands.

The router is the piece of code responsible for taking a request and executing the appropriate entry in the registry. (Pronto also comes with a built-in HTTP server which sends HTTP requests to a router. We'll look at that another time.)

Once we have our registry and our router, we can build our first chain of commands:

registry.route('hello')
  .does(Hello)

A route must have a name (hello) and can have one or more commands, each noted by a call to does().

In the example above, the route hello executes one command -- the Hello command (actually pronto.commands.Hello).

Finally, we execute our route like this: router.handleRequest('hello');

That list line looks in the registry for a route named hello. When it finds our hello route, it executes the each command on the route, in order, managing all of the asynchronous bits for us.

Chains

So if each route can have more than one command, how can we execute multiple commands? Here's an example that executes three Hello commands in a row:

registry.route('hello')
  .does(Hello)
  .does(Hello)
  .does(Hello)
  ;

For a real application, though, you will want to build your own commands to execute steps of a sequence.

Since commands can pass data down the chain (using the Context), a more practical application would pass data from one command to the next. We'll see that in an upcoming article.

Conclusion

This article has tried to provide a quick introduction to building a simple application in Pronto. Pronto's chains, though, are far more powerful when used to pass data from one command to another, processing things in bite-sized chunks. That is the topic of a future article, or you can take a look at the Pronto.js wiki.