Node.js and ECMAScript 6 (ES-2015, ES-2016, and so on)

In 2015, the ECMAScript committee released a major update of the JavaScript language. The browser makers are adding those much-needed features, meaning the V8 engine is adding those features as well. These features are making their way into Node.js starting with version 4.x.

Note

To learn about the current status of ES-2015 in Node.js, visit https://nodejs.org/en/docs/es6/.

By default, only the ES-2015 features which V8 considers stable are enabled. Further features can be enabled with command-line options. The almost complete features are enabled with the --es_staging option. The features still in progress are enabled by the --harmony_destructuring option. The website documentation gives more information.

The ES-2015 features make a big improvement in the JavaScript language. One feature, the Promise class, should mean a fundamental rethinking of common idioms in Node.js programming. In ES-2016, a pair of new keywords, async and await, will simplify coding asynchronous code in Node.js, and it should encourage the Node.js community to further rethink the common idioms of the platform.

There's a long list of new JavaScript features, but let's quickly go over two of them we'll use extensively.

The first is lighter weight function syntax called the Arrow Function:

fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) …; // do something with the error
  else …;  // do something with the data
});

This is more than the syntactic sugar of replacing the function keyword with the fat arrow. The value of this is the same as it was outside this invocation. This means that, when using an arrow function, we don't have to jump through hoops to bring this into the callback function because this is the same at both levels of the code.

The next feature is the Promise class, which is used for deferred and asynchronous computations. Deferred code execution to implement asynchronous behavior is a key paradigm for Node.js, and it requires two idiomatic conventions:

  • The last argument to an asynchronous function is a callback function which is called when asynchronous execution is to be performed
  • The first argument to the callback function is an error indicator

While convenient, these conventions resulted in multilayer code pyramids that can be difficult to understand and maintain:

doThis(arg1, arg2, (err, result1, result2) => {
    if (err) …;
    else {
         // do some work
         doThat(arg2, arg3, (err2, results) => {
              if (err2) …;
              else {
                     doSomethingElse(arg5, err => {
                             if (err) .. ;
                             else ..;
                     });
              }
         });
    }
});

Depending on how many steps are required for a specific task, a code pyramid can get quite deep. Promises will let us unravel the code pyramid and improve reliability because error handling is more straightforward and easily captures all errors.

A Promise class is created as follows:

function doThis(arg1, arg2) {
    return new Promise((resolve, reject) => {
        // execute some asynchronous code
        if (errorIsDetected) return reject(errorObject);
        // When the process is finished call this:
        resolve(result1, result2);
    });
}

Rather than passing in a callback function, the caller receives a Promise object. When properly utilized the above pyramid can be coded as follows:

doThis(arg1, arg2)
.then((result1, result2) => {
  return doThat(arg2, arg3);
})
.then((results) => {
  return doSomethingElse(arg5);
})
.then(() => {
   // do a final something
})
.catch(err => {
   // errors land here
});

This works because the Promise class supports chaining if a then function returns a Promise object.

At the time of writing, the Node.js community has barely begun to use this new paradigm, and instead it is still using the old pass in a callback function paradigm. In the interim, we'll have to be flexible enough to use both paradigms. Over the long term, there should be a switch to this paradigm.

Using Babel to use experimental JavaScript features

The Babel transpiler (http://babeljs.io/) is a great way to use cutting edge JavaScript features on older implementations. The word transpile means Babel rewrites JavaScript code into other JavaScript code, specifically to rewrite ES-2015 or ES-2016 features to older JavaScript code. Babel does this by converting JavaScript source to an abstract syntax tree, then manipulating that tree to rewrite the code using older JavaScript features, and then writing that tree to a JavaScript source code file.

Since Node.js doesn't yet support all the ES-2015 features, we can use Babel to go ahead and use those features.

Note

We're not ready to show example code for these features, but we can go ahead and document the setup of the Babel tool. For further information on setup documentation, visit http://babeljs.io/docs/setup/.

In the root directory of your project, type these commands:

$ npm install --save-dev babel-cli
$ npm install babel-preset-es2015 –save-dev

This installs the Babel software, saving references in the package.json file. We'll go over that file in more depth in the next chapter, but NPM uses package.json to document attributes of the module. Some of those attributes are dependencies on other modules, and in this case, we're documenting a development dependency on Babel.

Because we installed babel-cli, a babel command is installed such that we can type the following:

$ ./node_modules/.bin/babel –help

Next, in the same directory as package.json, create a file named .babelrc containing the following:

{
  "presets": ["es2015"]
}

This instructs Babel to use presets to configure the set of transformations it will perform.

The last step is to create a directory named src to store code written with ES2015 or ES2016 features. The transpiled code will land in the directory named lib and it's that code which will be executed.

To transpile your code, run the following command:

$ ./node_modules/.bin/babel src -d lib

This command asks to take all files in the src directory and transpile each to a matching file name in the lib directory.

To automate the process, edit the package.json file and insert the following snippet:

"scripts": {
     "build": "babel src -d lib"
},

With this, you can use the following command:

$ npm run build

We'll go over npm scripts in more depth later, but this is a way to record certain commands for later use.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset