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.
15 replies on “Using ES7 async/await today with Babel”
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.
[…] [3] https://masnun.com/2015/11/11/using-es7-asyncawait-today-with… […]
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
[…] 内部的にはジェネレータと似たような挙動ですが、ジェネレータとPromiseの組み合わせよりもこちらの利用を強くお勧めします。ES7とBabelをすぐ活用したいなら、優れた資料がこちらにあります。 […]
[…] 在 js 引擎中,它所实现的和 Generators 其实是一样的,我更推荐在 Generators + Promises 之上使用 async await,更多的资源和使用 ES7 和 用 babel 转化可以看这里。 […]
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.
Great, it works with IE11 as well!
Thanks a lot (:
Thank you just solved the problem
Thank you just solved the problem