眾所周知,解決Nodejs異步問題的終極方案就是使用async/await
方案,但是每次在項目中配置都會或多或少有些問題,每次都會被幾個組件
- babel-core
- babel-polyfill
- babel-preset-es2015
- babel-preset-stage-0
- babel-plugin-*
搞的有點混淆不清,甚至不知所措,我們的項目環境利用expressjs搭建,不同程度的使用了es6甚至es7的語法特性和新的API,所以babel轉碼
我們先看下具體的CASE
CASE
nodejs 4.4.7
Case 1
去掉 app.js
里邊的 // import 'babel-polyfill'
和 // import 'babel-core/register'
, .babelrc
里邊需要有plugins
{
"presets": [
"es2015",
"stage-0"
],
"plugins": [
["transform-runtime", { "regenerator": true }]
]
}
帶有async的代碼正常能run起來。
Case 2
去掉 app.js
里邊加上 import 'babel-polyfill'
,babel里邊正常
{
"presets": [
"es2015",
"stage-0"
],
"plugins": [
]
}
帶有async的代碼能正常run
import 'babel-polyfill
換成import "babel-core/register"
代碼無法run起來,報錯

nodejs v7.4.0
Case 1
app.js 中引入import 'babel-polyfill'
而 .babelrc 如下
{
"presets": [
"es2015",
"stage-0"
]
}
代碼能正常run起來。
去掉
import 'babel-polyfill'
或者替換為import "babel-core/register"
代碼均不能正常run
Case 2
app.js 中去掉 import 'babel-polyfill'
,而 .babelrc 代碼加入
{
"presets": [
"es2015",
"stage-0"
],
"plugins": [
["transform-runtime", { "regenerator": true }]
]
}
代碼可以正常run。
得到結論
如果需要使用async和await有兩種方式,
- 在程序的入口處第一行引入
import babel-polyfill
. - 或者使用babel轉碼的時候引入插件
["transform-runtime", { "regenerator": true }]
往下探索
首先我們要搞清楚async和await屬於es2016(es6實際上是2015年發布的,es6常被稱為es2015,而es2016其實就是es7)的特性,Nodejs在實現標准版本的進程上相對瀏覽器側要快,截止到nodejs6.x的版本上,想要使用async和await還需要babel的轉碼才能實現。
還是看Case
例如如下代碼
const fs = require('fs')
async function readFiles (fileName) {
return new Promise(function(resolve, reject) {
fs.readFile(fileName, function(error, data) {
if (error) reject(error)
resolve(data)
})
})
}
const start = async function() {
const result = await readFiles('/Users/liujb/Desktop/aa.txt')
console.log(result.toString())
}
start()
親測在v7.4.0
下報語法錯誤,在v7.7.4
下能run。


關於babel

from
以上內容還是很清晰的,通過babel轉碼會默認讀取babelrc設定的規則,同時會運用相應的插件。
關於插件
babel-register and babel-polyfill
仔細閱讀阮老師的博客
babel-register是一個鈎子,會對require的js、es、jsx、es6后綴的文件進行轉碼,且不會對當前文件進行轉碼,而且是實時轉碼所以只適合開發階段。
babel-polyfill對es6的API進行轉碼,bable只會對syntax進行轉碼。
babel-plugin-*
babel-plugin-* 代表了一系列的轉碼插件,如babel-plugin-transform-es2015-arrow-functions 用於轉碼 es6 中的箭頭函數,babel-plugin-transform-async-to-generator 用於將 es7 中的 async 轉成 generator。
babel-preset-*
我們現在有了 babel-plugin 系列,可以按需配置自己想要的特性。但若是想搭個 es6 環境,一個個地配置各個插件,我猜你會瘋掉。babel-preset 系列就可以滿足我們的需求,babel-preset 系列打包了一組插件,類似於餐廳的套餐。如 babel-preset-es2015 打包了 es6 的特性,babel-preset-stage-0 打包處於 strawman 階段的語法
babel-plugin-transform-runtime

以上內容來源於https://github.com/brunoyang/blog/issues/20
小結
這一路下來,發現了不少的好文章,終於解決了自己的一些困惑,還是那句廢話知易行難,學習總是靠一點點堅持。
參考
- http://stackoverflow.com/questions/33527653/babel-6-regeneratorruntime-is-not-defined-with-async-await
- http://stackoverflow.com/questions/28976748/regeneratorruntime-is-not-defined
- https://www.zfanw.com/blog/babel-6.html
- transform-runtime
- babel-plugin-transform-runtime
- https://github.com/lmk123/blog/issues/45