Getting Started with Pronto.js
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.