Let’s take a code snippet that contains the demonstration of async/await — https://gist.github.com/patrickarlt/8c56a789e5f185eb9722 – our objective is to transpile this piece of code to ES5 (current day Javascript) so we can run it with today’s version of NodeJS.
You will notice a command on top of the snippet which no longer works because Babel JS has changed. I am going to describe how we can do it with the latest version of babel as of this writing (6.1.4 (babel-core 6.1.4)).
Install Babel and Plugins
The new Babel depends on individual plugins to transform and parse codes. To transform async functions, we shall use the transform-regenerator
plugin. We also need to add the syntax plugin to recognize the async/await syntax. Otherwise Babel won’t recognize those. Apart from that, we also install the ES2015 preset which includes a sane set of plugins for transforming ES6 to ES5. We will keep those so we can use other ES6 goodies.
First we install babel-cli globally:
1 |
npm install -g babel-cli |
Here’s our package.json file so you can just do npm install
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
{ "name": "awesome-async", "version": "1.0.0", "description": "", "main": "github.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "babel-plugin-syntax-async-functions": "^6.1.4", "babel-plugin-transform-regenerator": "^6.1.4", "babel-polyfill": "^6.1.4", "babel-preset-es2015": "^6.1.4", "request": "^2.65.0" } } |
Configuring Babel
Here’s the .babelrc
file I put in the same directory:
1 2 3 4 |
{ "presets": ["es2015"], "plugins": ["syntax-async-functions","transform-regenerator"] } |
The file tells babel how to transform your code.
Transpile & Run
Once we have installed the dependencies, we can then start transpiling the codes to JS:
1 2 |
babel github.es6 -o github.js node github.js |
You might run into a problem like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/Users/masnun/Projects/awesome-async/github.js:34 return regeneratorRuntime.async(function printPublicGists$(_context) { ^ ReferenceError: regeneratorRuntime is not defined at printPublicGists (/Users/masnun/Projects/node/github.js:34:10) at Object.<anonymous> (/Users/masnun/Projects/node/github.js:63:1) at Module._compile (module.js:460:26) at Object.Module._extensions..js (module.js:478:10) at Module.load (module.js:355:32) at Function.Module._load (module.js:310:12) at Function.Module.runMain (module.js:501:10) at startup (node.js:129:16) at node.js:814:3 |
It’s because we need to include the regenerator run time. The runtime is packed in the babel-polyfill
we have already installed. We just need to include it in our source code. So the final github.es6 file would look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
require("babel-polyfill"); import request from "request"; // promise returning function function get (url){ return new Promise(function(resolve, reject){ request({ method: 'GET', url: url, json: true, headers: { 'User-Agent': 'request' } }, function(err, resp, body){ if(err){ reject(err); } else { resolve(body); } }); }); } // create a new "async" function so we can use the "await" keyword async function printPublicGists(){ // "await" resolution or rejection of the promise // use try/catch for error handling try { var gists = await get('https://api.github.com/gists/public'); // now you can write this like syncronous code! gists.forEach(function(gist){ console.log(gist.description); }); } catch (e) { // promise was rejected and we can handle errors with try/catch! } } printPublicGists(); |
Now if we transpile and run again, it should work fine.