facebook google plus twitter
Webucator's Free Ajax Tutorial

Lesson: Intro to Ajax and the Node.js Server

Welcome to our free Ajax tutorial. This tutorial is based on Webucator's Ajax Training course.

The term AJAX is a pseudo-acronym for "Asynchronous JavaScript And XML," but is now used much more broadly to cover all methods of communicating with a server using JavaScript. As we will see, Ajax is not always asynchronous and does not always involve XML.

Node.js is an open-source, cross-platform server that runs JavaScript on the server-side; we'll use Node.js as the back end for our Ajax demos and exercises.

Lesson Goals

  • Learn the Purpose of Ajax.
  • Learn what Node.js is.
  • Learn how to install Node.js.
  • Learn how to run Node.js applications and as a server.
  • Learn how to modify Node.js applications.

The Purpose of Ajax

The main purpose of Ajax is to provide a simple and standard means for a web page to communicate with the server without a complete page refresh. To illustrate this, consider a simple registration form. You have very likely experienced the frustration of having to try multiple usernames when registering for some new website. You fill out the entire form, hit the submit button, wait for a second or so, and then get the same form right back with a message saying that the username you have chosen is not available. You try another easy-to-remember username and find it is also not available. You repeat this several times until finally you pick some obscure username. This process wouldn't be nearly as bad if you didn't have to wait for the entire page to refresh each time you tried a new username.

But that's a very simple example. Some web-based applications require constant interaction with a database through a middle-tier. Take, for example, an interface for updating employee records. The traditional way of doing this is illustrated below.

Traditional Web Application

  1. First, the application shows a list of employees to pick from: Employee List
  2. When the user chooses an employee, the server returns a new page (FIRST REFRESH) and a form is displayed: Form
  3. The user can then edit the employee data (e.g, change "Nancy" to "Nance") and submit the form. The server then returns the new page (SECOND REFRESH):New Page
  4. To get back to the employee list to begin the process of modifying another employee's data, the user would have to click on the "Employee List" link (THIRD REFRESH).

Ajax makes this process much simpler for the user. Records, and even individual fields of a record, can be edited one at a time without full page refreshes. This method will be illustrated shortly, but first, we must take a little detour to get the back end set up for server-side communication.

JavaScript on the Server Side?

Given that in this course we will be using JavaScript (in the form of Node.js) for some of the server-side components, we're going to examine how it all works. Please use this section as a quick guide on how to run the demos and exercises you see later in the course; we've also included some background on Node.js, but you can skim that if you aren't interested.

Node.js is a "platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices." Much like PHP, ColdFusion, Microsoft .NET, or JavaServer Pages, Node.js (pronounced to rhyme with "Toad Say Yes") is an application server. You might use Node.js to connect to a database (returning a result set from a query, say, or updating a record); deliver HTML, XML, or JSON content; connect to local files; or serve up static web pages like Apache or another web server.

Why Node.js?

Since you write Ajax code in JavaScript throughout this course, it made sense to choose a server-side technology also based in JavaScript; as such, we picked Node.js - perhaps the most stable and most prevalent of the JavaScript-based server-side solutions that have gained in popularity over the past decade.

A useful byproduct of the move to Node.js is consistency: It used to be the case that we presented this course to students with a choice of server-side technologies (Classic ASP, ColdFusion, PHP, and JSP) and asked them to set one of these up on their computer. We need the server-side technologies to serve up database-query pages (since the Ajax pages have to query something in the background to get, and thus return, some content). But given the differences among students's setups - PC vs. Mac, personal laptop vs. corporate network station, etc. - we found that setting up Node.js offered an easy way to provide server-side resources in a consistent manner for all students.

Installing Node.js

Please refer to the setup instructions for installing and running Node.js here: https://www.webucator.com/portal/wiki/index.cfm/JSC401

Running Node.js

We will use Node.js both as a web server to serve static HTML files and their associated CSS and JavaScript components. We will also use Node.js to serve dynamic responses, which will serve as the back end of our Ajax applications. An Ajax-enabled web page might, for instance, allow the user to display details for a desired person by clicking on that person's name on a list displayed on the page; the click would generate an Ajax call to a "behind the scenes" page that queries a database. The Ajax call carries with it the ID of the desired person's record. We'll use Node.js to serve up the "page" that returns the database query. Let's look at a simple example.

A First Node.js Application & Server

In your class files, navigate to the directory IntroAjaxNodeJsServer/Demos/. In it you will find the following files/directories:

  1. package.json
  2. server.js
  3. Northwind.sqlite (a database - we won't use it in this example, but will make use of databases later in the course)

package.json defines this particular Node.js application; most importantly, the file defines the Node.js modules needed for this app. Modules enable functionality - connecting to a database, say, or browsing a directory from the web server - and are usually downloaded via npm, the Node.js package manager. All of the Node.js applications in this course will have all the needed modules already installed.

Navigate to the same directory mentioned above from the command line (Terminal on a Mac, Command Prompt on a Windows PC). To do so, on either Windows or Mac, type cd ("change directory") and the path to the directory. On a PC, you will use backslashes ("\"); on a Mac, you will use forward slashes ("/").

On a PC, for instance, one would type cd c:\webucator\ClassFiles\IntroAjaxNodeJsServer\Demos if the class files were stored in a directory named webucator in the root of the c: drive. A Mac user would type cd ~/Documents/webucator/ClassFiles/IntroAjaxNodeJsServer/Demos if the class files were stored in a directory named webucator inside the user's Documents directory; note that, on a Mac, ~ refers to the root of the current user's directory.

Next, type npm install from the command line: this will download the needed modules, as defined in package.json. Node modules will install to the directory node_modules.

After modules have installed, type npm start to start the application.

When needed, press CTRL+c on the command line to stop the Node.js server instance.

server.js defines the application itself: this is the file that runs when you started the Node.js application, which defines how the application makes use of Node.js modules, and which starts the web server on a specific port. Note the when you open up server.js with your web editor, the last line - app.listen(8080); - starts the web server (an HTTP server) and listens on port 8080 so that, once the application is running, visitors can browse to http://localhost:8080 to view files served by and response routes defined by this application.

server.js also defines a set of response routes; in this example, these are the GET routes /HelloWorld and /HelloWorldJade. Each route is a function in server.js, defining the method (usually GET or POST), the actual route (/HelloWorld, for example), and how to respond, defined as an anonymous function. We will review each of these in detail.

app.get('/HelloWorld', function(req, res) {
  var name = req.param('name') || 'Somebody';
  var respondWith = '<?xml version="1.0" encoding="UTF-8"?>';
  respondWith += "<h1>Hello " + name + "!</h1>";
  res.status(200);
  res.setHeader('Content-type', 'text/xml');
  return res.send(respondWith);
});

The first line of code, app.get('/HelloWorld..., defines a GET route, meaning that, once this Node.js application is running, users will be able to visit http://localhost:8080/HelloWorld in their browser to view the response from this route.

var name = req.param('name') || 'Somebody'; attempts to read a GET parameter from the request made for this response route. If the user browses to http://localhost:8080/HelloWorld?name=Jane, for example, then local variable name will have value "Jane". If the user browses to http://localhost:8080/HelloWorld then local variable name will get the default value "Somebody".

The next few lines of code define the response sent back to the browser: we send back XML, encoded as UTF-8, with a single h1 tag containing Hello [name]. The very last line, return res.send(respondWith);, sends the response back to the browser.

We will also make use of Jade, a templating engine for Node.js, which allows us to define some parts of the response in a template file (usually ending with a .jade extension). Let's look at the other response route defined in our server.js file:

app.get('/HelloWorldJade', function(req, res) {
  var name = req.param('name') || 'Somebody';
  res.render('HelloWorld.jade', {
    'name': name
  }, function(err, html) {
    if (err) {
      res.redirect('/404');
    } else {
      res.status(200).send(html);
    }
  });
});

Similar to our first example, this response route defines what the user sees when going to http://localhost:8080/HelloWorldJade in their browser. The code which gets the name parameter, or sets its default value, if the parameter is not present, is the same as we saw previously.

Different this time is the manner in which we craft the response sent back to the server. As you might expect, for a more complicated response like a long web page with a considerable volume of content, for example, it quickly becomes unwieldy to build the response string in the response route definition in server.js itself. As such, using Jade templates - as we have done here - allows us to structure much of the response in a separate file, using a simplified syntax.

The line in server.js that starts res.render('HelloWorld.jade', {'name': name}, function(err, html) {... specifies the way in which we return content to the browser. The first parameter tells Node.js that we want to serve up the HelloWorld.jade template as the response for this route. The second parameter ({'name': name}) in our call to render passes our name variable to the template so that the template has the value of name available to it. The final parameter is a callback function by which we actually send back the data; note that we check to see if the template exists and, if not, redirect the user to a "page not found" error. (On a production site our error handling would likely be more robust - checking for more sources of error than just the template not existing.)

In the template HelloWorld.jade:

doctype html
html(lang="en")
  head
    title Hello World

  body
    h1 Hello #{name}

Jade is a templating engine designed for use with Node.js. It offers a simplified syntax to specify the type of page (an HTML5 page, in our case) and to display content. In our example here, we use Jade to give the page a title tag with value Hello World and, on the last line, use interpolation to display the variable name as the value the "Hello" h1 tag. Recall that the template gets the value of the variable name from the response route: the value defaults to Somebody or gets its value from the GET parameter passed in the request, if present.

You can find more information about the Jade template engine at http://jade-lang.com/.

An Ajax Web Application

We're now ready to revisit our Employee Admin application from earlier, but this time using the power of Ajax. Again, our Ajax applications will communicate with Node.js-served response routes.

Before viewing AjaxBasics/Solutions/EmployeeAdmin.html in your browser, be sure to first navigate to that directory (AjaxBasics/Solutions/) from the command line and type npm install. This will install all needed Node.js modules. Then type npm start to start the Node.js server. You will then be able to browse to http://localhost:8080/EmployeeAdmin.html

  1. Like with the "traditional" method, the Ajax application shows a list of employees to pick from (AjaxBasics/Solutions/EmployeeAdmin.html):Employees List
  2. When the user chooses an employee, the page doesn't reload. Instead, an Ajax call to the server is made, the server returns the HTML form and JavaScript is used to display the form on the page:Call to Server The "server" side - the behind-the-scenes resource to which our Ajax application makes requests and receives responses - is, in our case, a Node.js server, but might have been ColdFusion, Microsoft .NET, PHP, or many other types of application server/middleware.
  3. The user can then edit the form fields. Each time a changed form field loses focus the change is sent to the server with Ajax, the server-side code updates the data in the database and sends back the updated list of employees to the browser. JavaScript is again used to display the updated list on the page. The screenshot below shows the state after the user has changed the field but before she has tabbed out:State
  4. The employee list is updated to reflect the changes made. Notice "Nancy" has been changed to "Nance" in the list. A message is displayed letting the user know that the database was updated: Displayed Message

All this is accomplished without having to do even one complete refresh. This is the major benefit of Ajax.

Adding a New Route to a Node.js Application

Duration: 10 to 15 minutes.

In this exercise, you will modify our Node.js application to add a new response.

  1. Open IntroAjaxNodeJsServer/Exercises/server.js in your editor.
  2. Copy the existing HelloWorld response route and paste it as a new response route right below it.
  3. Name the new route NodeExercise.
  4. Define two params - fname and lname - and give them default values.
  5. Change the output to respond with "Hello First Last!" (or the appropriate values, if the parameters exist).
  6. Navigate to IntroAjaxNodeJsServer/Exercises/ in the command prompt/terminal and type npm install to install any needed Node.js modules.
  7. Type npm start to start the Node.js server.
  8. Test your solution in a browser by visiting http://localhost:8080/NodeExercise

Solution:

IntroAjaxNodeJsServer/Solutions/server.js
express = require('express');
var bodyParser = require('body-parser');
var app = express();
var directory = require('serve-index');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));
var sqlite3 = require('sqlite3').verbose();

//use pug templating engine:
app.set('views', __dirname);
app.set('view engine', 'pug');

app.get('/HelloWorld', function(req, res) {
  var name = req.param('name') || 'Somebody';
  var respondWith = "

Hello " + name + "!

"; res.status(200); res.setHeader('Content-type', 'text/html'); return res.send(respondWith); }); app.get('/NodeExercise', function(req, res) { var fname = req.param('fname') || 'First'; var lname = req.param('lname') || 'Last'; var respondWith = "

Hello " + fname + " " + lname + "!

"; res.status(200); res.setHeader('Content-type', 'text/html'); return res.send(respondWith); }); app.get('/HelloWorldpug', function(req, res) { var name = req.param('name') || 'Somebody'; res.render('HelloWorld.pug', { 'name': name }, function(err, html) { res.status(200).send(html) }); }); //allow for directory browsing: app.use(directory(__dirname)); app.use(express.static(__dirname)); //web server listens on port 8080: app.listen(8080);

We copied the HelloWorld route and pasted it as a new route, renaming the route to NodeExercise so that the user can visit http://localhost:8080/NodeExercise in a browser. We define two parameters fname and lname, reading them from the request if they exist or giving them default values if not. We change the displayed response to include both parameters.