我尝试
require('fs').writeFileSync('o.json', JSON.stringify(anObject));
为了调试,我得到了RefrenceError: require is not defined.
这很奇怪。什么样的环境没有require
?
在Node.js中,require
函数不是全局定义的。当您需要一个模块时,它的源代码由一个接受多个参数的函数包装,require
就是其中之一:
(function (exports, require, module, __filename, __dirname) {/* your code */
});
当您查看任何源文件的内容时,都可以在Node Inspector中看到该包装器。
现在有两种不同的场景可以从Node Inspector的控制台评估代码:
已调试的进程正在运行。表达式是在全局上下文中计算的,即您只能访问全局定义的符号。CCD_ 5不在其中。
已调试进程在断点处暂停。表达式是在选择堆栈帧的上下文中计算的,并且可以访问当前范围中的所有变量(包括外部函数从闭包捕获的变量)。但是:大多数函数都不调用
require
,因此这个变量在任何闭包中都不会被捕获,您也无法访问它
我和一位Node核心开发人员就将require公开为全局符号进行了简短的交谈,因为这将简化从Node Inspector注入代码的过程,但我的论点还不够令人信服。
可以在节点检查器中使用require
,方法是在"require"在范围内的地方点击断点(使用NodeJS v0.10.25测试,node-inspector@0.7.0-2):
一个示例(Node的超简单的2字节"REPL"):创建一个仅包含以下内容的文件(例如r.js
):
0;
然后使用
$ node --debug-brk r.js
并以通常的方式启动节点检查器和浏览器,
-或-(使用来自NPM的节点调试模块)使用:
$ node-debug r.js
现在切换到浏览器中的节点检查器控制台,验证是否确实定义了require
,然后对其执行一些操作,如:
> typeof require;
"function"
> fs = require('fs');
undefined
> fs.writeFileSync('bla.txt', 'blup');
undefined
并验证该文件是否已写入启动节点的目录中。
注意:节点检查器的浏览器部分可能会出现故障:当一个接一个地调试不同的脚本时,我通常需要刷新(导致调试器断开连接),然后重新启动node,直到脚本在浏览器中正确显示。
附言:这个方法与创建一个Perl"REPL"有着惊人的相似之处,它是以perl -de '0;'
的形式运行的。。。巧合
FWIW,只需从node-debug _mocha
开始,在断点处停止,并在右侧面板中选择调用堆栈上的最低帧,我就可以获得require()
可用的上下文:require('fs')
工作正常,但require('q')
和其他安装的模块不工作,即使我指定了绝对路径。如果我找到解决方案,我会回来的。
require()
在所有CommonJS环境中实现,包括Node.js,但不在浏览器控制台中实现,这正是node-inspector
的基础(具体地说,是Blink Developer Tools):
> require
ReferenceError: require is not defined
我发现了一种非常简单的方法来实现这一点。
首先,node inspect
进入目标进程($pid
):
$node inspect -p $pid
connecting to 127.0.0.1:9229 ... ok
接下来,输入";调试REPL":
debug> repl
Press Ctrl+C to leave debug repl
接下来,通过process.mainModule
:获取主模块的require
功能的参考
> require = process.mainModule.require
[Function: function]
就是这样。如果我们想使用它,我们会像往常一样使用:
> dns = require('dns')
{ lookup: ,
lookupService: ,
Resolver: ,
setDefaultResultOrder: ,
setServers: ,
... }
> dns.lookup('google.com', function(){result = arguments})
{ callback: , family: 0, hostname: 'google.com', oncomplete: }
> result
[ null,
'142.251.16.139',
4,
callee: ,
Symbol(Symbol.iterator): ]
需要注意的几件事:
- 这将污染目标进程的全局命名空间。在你的情况下,这可能是个问题,也可能不是
- 这假设存在目标进程的主模块入口点
process.mainModule
自v14.0.0
以来已弃用