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.
I woulI would recommend , these tools for JSON http://codebeautify.org/jsonviewer and http://jsonformatter.org
Thanks, I shall try it out!
How about the transform-async-to-generator plugin, which is included in the stage-3 preset? I’m trying to find the best way to use async functions in Node 5 with babel-preset-es2015-node5, but encountering a problem. I would be very appreciative if you had some time to look at my stackoverflow question.
Pingback: acjohnson55 comments on "Pogoscript – a compile-to-JS language that emphasises concurrency, readability"
Yes, im curious the difference between the runtime-regenerator and the transform-async-to-generator. I’m dealing with lots of debugging issues, see this: https://github.com/amcdnl/debug-hell
transform-async-to-generator plugin appears to transpile syntax of async/await into syntax of */yield. It also appears to make the behavior of those generator functions *act* like the intended async functions with a small code addition. **This is ES7 to ES6**
regenerator was created by Facebook team (See: https://facebook.github.io/regenerator/)– it transpiles generator functions into ES5-compliant syntax. In order to run those ES5 functions, however, requires the regeneratorRuntime code to be included with your code. If you use es2015 preset in Babel, it looks like it wraps each generator function with a hook into regeneratorRuntime–so the Babel es2015 preset is expecting you will include the regeneratorRuntime with your code. **regenerator is ES6 to ES5**
If you’re not sure what a plugin/preset is doing, just try each one at a time in .babelrc settings and try transpiling a simple example!
Should be enough to use “babel-preset-stage-3” and omit “syntax-async-functions”,“transform-regenerator”.
Or simply use plugin
transform-async-to-generator
Then you have not to transpile and then run but use babel-node to run your script (and omit babel-polyfill).
DavidC is correct. You don’t need any polyfill, or even the es2015-preset.
All you need to do is:
1. Edit package.json and add a section for babel (this works the same as .babelrc, but is one less file):
"babel": {
"plugins": [
"transform-async-to-generator"
]
}
2. Install the plugin:
npm install babel-plugin-transform-async-to-generator --save-dev
3. Run babel-node:
node_modules/babel-cli/bin/babel-node.js
Pingback: ES6 チートシート | プログラミング | POSTD
Pingback: 【转】ES6 手册 - 屌丝程序员
How can I get
to work in browser?
I still get error: “
” and “require is not defined”.Please check out their docs. Can’t remember right now.