随着ES2017的推出,async/await成为了JavaScript开发中最常用的异步编程方式之一。Babel则成为了开发人员们将这些新特性应用到旧代码中的首选转译工具。然而,在Babel7中,升级async/await代码后出现了一些问题,许多开发者不知如何解决。在本篇文章中,我们将带着大家深入探究这些问题,并为大家提供实用的解决方案。
问题
在Babel7中,async/await存在的问题主要与它的转译方式有关。许多开发者经常会看到像这样的警告信息:
Warning: The code generator has deoptimised the styling of <filepath>. Please report this to the Babel team.
这是因为Babel7中的async/await被转换成生成器和迭代器,使代码不再具有语法优化,从而影响了性能。
在旧版Babel中,async/await的代码将直接被转换成ES2015代码,这更接近JavaScript原生的实现方式,但这种方式也有其自身的问题。例如,在IE浏览器中,async/await将被忽略而无法工作。
在升级到Babel7版本后,由于async/await的转换方式改变,上述问题变得更加突出。
解决方案
使用Transform-runtime插件
Transform-runtime是Babel7中的一个插件,它使用了babel-runtime中的polyfill与helper函数来进行转换,从而解决了许多问题。
首先,我们需要安装这个插件:
npm install --save-dev @babel/plugin-transform-runtime
然后,在.babelrc配置文件中配置该插件:
// www.javascriptcn.com code example
{
"presets": [
["@babel/env", {
"targets": {
"browsers": [
"last 2 versions",
"not ie < 11",
"not android < 4.4"
]
}
}],
],
"plugins": [
["@babel/plugin-transform-runtime", {
"corejs": false,
"helpers": true,
"regenerator": true,
"useESModules": false
}]
]
}"corejs": false 表示我们不使用core-js。
"helpers": true 表示我们使用runtime的helper函数。
"regenerator": true 表示我们使用regenerator。
"useESModules": false 表示我们使用的不是ES模块。
使用Transfrom-Async-To-Generator插件
Transfrom-Async-To-Generator是另一个Babel插件,它可以将async函数转换成生成器函数,使得async/await可以更合理、更有效率地工作。
首先,安装该插件:
npm install --save-dev @babel/plugin-transform-async-to-generator
然后,在.babelrc配置文件中添加该插件:
{
"plugins": [
"@babel/plugin-transform-async-to-generator"
]
}通过添加这两个插件,我们可以更好地处理async/await问题,提高代码性能,并且使得转换后的代码在更多的浏览器和环境中运行得更好。
示例代码
const fetchUser = async (id) => {
const res = await fetch(`/users/${id}`);
return res.json();
};这段代码将会被转化为下面这样的代码:
// www.javascriptcn.com code example
var _asyncToGenerator = require("@babel/runtime/helpers/asyncToGenerator");
var _regeneratorRuntime = require("@babel/runtime/regenerator");
var fetchUser =
/*#__PURE__*/
function () {
var _ref = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee(id) {
var res;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return fetch("/users/".concat(id));
case 2:
res = _context.sent;
_context.next = 5;
return res.json();
case 5:
return _context.abrupt("return", _context.sent);
case 6:
case "end":
return _context.stop();
}
}
}, _callee);
}));
return function fetchUser(_x) {
return _ref.apply(this, arguments);
};
}();使用Transform-Async-To-Generator插件后,转换后的代码会变成下面这个样子:
// www.javascriptcn.com code example
var fetchUser =
/*#__PURE__*/
_regeneratorRuntime.mark(function fetchUser(id) {
var res;
return _regeneratorRuntime.wrap(function fetchUser$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return fetch("/users/".concat(id));
case 2:
res = _context.sent;
_context.next = 5;
return res.json();
case 5:
return _context.abrupt("return", _context.sent);
case 6:
case "end":
return _context.stop();
}
}
}, fetchUser);
});我们可以看到,使用Transform-Async-To-Generator插件后,转换后的代码更简洁,更高效。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d032e6e46428fe9ecef21b