function-timeout 是一个可以使同步函数支持超时的 npm 库,实现原理是把函数放在 node:vm 中执行,因为 vm.Script() 返回的 script 对象就支持传入 timeout 选项。
vm 是 virtual machine 的缩写,意思是在 Node.js 中创建一个虚拟环境,用来执行不希望在主环境中执行的代码。
创建一个 script 对象:
const script = new vm.Script('returnValue = function_()');
vm.Script() 接收一个字符串,这个字符串就是即将要在 vm 中运行的代码,具体到上面这个例子,就是要在 vm 执行 returnValue = function_() 这段代码,即把 function_() 返回的结果赋值给 returnValue 变量。
那 function_ 是什么东东?它是在哪里被定义的?
function_ 是定义在 vm 的 context 中的,context 是一个重要概念,它本身就是 Node.js 的重要概念,所以也是 vm 的重要概念。
All JavaScript executed within Node.js runs within the scope of a "context".
写一个 context 对象,在这个 context 中定义 script 需要用到的变量,这里只有 function_:
const context = {
function_: () => function_(...arguments_),
};
然后执行 script,runInNewContext 意思是在新的 context 中执行代码,但需要告诉它 context 是哪个,另外正如开头所说的,它支持传入超时时间:
script.runInNewContext(context, {timeout});
如果执行超时,Node.js 会抛出 ERR_SCRIPT_EXECUTION_TIMEOUT 错误码。
那怎么获得 returnValue 的值呢?returnValue 也是通过 context 获取:
context.returnValue;