「提问」Nodejs中babel转译的async/await,执行了一个while(true) {},为啥不会卡住
「提问」Nodejs中babel转译的async/await,执行了一个while(true) {},为啥不会卡住
最近对async/await
的实现产生了兴趣,看了下babel
的转译,调用了regeneratorRuntime
的几个函数。
打开源码看了一下午,有很多东西不是很理解。
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return setTimeout(function (v) {
return console.log(v);
}, 1000);
case 2:
case "end":
return _context.stop();
}
}
以上代码我目前的理解是执行了个状态监听器,await
后的函数执行完毕后会改变_context.next
,然后结束这个状态机。
但在 console 中,执行while(true){}
页面几乎是秒卡的。
求指教!
以上运行环境为 chrome console 。
async function log (v) {
await setTimeout(v => console.log(v), 1000)
}
babel =>
"use strict";
var log = function () {
var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(v) {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return setTimeout(function (v) {
return console.log(v);
}, 1000);
case 2:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return function log(_x) {
return _ref.apply(this, arguments);
};
}();
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = genkey; var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step(“next”, value); }, function (err) { step(“throw”, err); }); } } return step(“next”); }); }; }
因为有 return ,所以循环只会跑一次……而且 setTimeout() 返回的并不是一个 Promise ,用 await 怪怪的吧。
while (1) 其实是给 loop 里有 await 的用的,比如 for (let i = 10; i–; ) await Promise.resolve();
如果可以直接 goto 到某个 label 的话,就不需要这个 while (1) 了。
我也没研究过 Babel transpile 出来的代码,好像只要 await 在控制流程语句或者 try…catch block 里就没法在 switch 里一路 fallthrough 下去,需要跳转到隔开的某个状态里。
async 内部 return 的好像就是一个 promise:
function _asyncToGenerator(fn) {
return function() {
var gen = fn.apply(this, arguments);
return new Promise(function(resolve, reject) {…
});
};
}
var log = function () {
var _ref = _asyncToGenerator(…);
return function log(_x) {
return _ref.apply(this, arguments);
};
}();
之前没有注意到 while 里面那个 return ,下一步往哪里挖有了许多头绪,谢谢指教!
在Node.js中,使用Babel转译async/await
语法时,本质上是通过将async
函数转换为返回Promise对象的函数,并将await
表达式转换为Promise的.then()
调用,从而实现对异步操作的支持。然而,当你在async
函数中使用while(true) {}
这样的无限循环时,实际上是在同步地阻塞JavaScript的事件循环。
以下是一个示例代码,展示了这种情况:
const babel = require('@babel/core');
const code = `
async function test() {
while(true) {}
console.log('This will never run');
}
test();
`;
const { code: transpiledCode } = babel.transformSync(code, {
presets: ['@babel/preset-env']
});
console.log(transpiledCode);
// 运行transpiledCode,Node.js进程将会被阻塞,因为while(true) {}是同步阻塞的
// 在实际运行环境中,下面的代码不会执行到
// console.log('After test');
在Node.js中,尽管Babel处理了async/await
的语法糖,使其看起来像是异步操作,但while(true) {}
这样的同步阻塞代码依然会阻塞事件循环,导致Node.js进程无法处理其他事件或执行其他代码。因此,你的程序会“卡住”,不会继续执行后面的代码或响应其他事件。
简而言之,Babel的转译不会改变while(true) {}
同步阻塞的本质。