企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# REPL ~~~ 稳定度: 3 - 稳定 ~~~ 一个 Read-Eval-Print-Loop(REPL,读取-执行-输出循环)既可用于独立程序也可很容易地被集成到其它程序中。REPL 提供了一种交互地执行 JavaScript 并查看输出的方式。它可以被用作调试、测试或仅仅尝试某些东西。 在命令行中不带任何参数执行 `node` 您便会进入 REPL。它提供了一个简单的 Emacs 行编辑。 ~~~ mjr:~$ node Type '.help' for options. > a = [ 1, 2, 3]; [ 1, 2, 3 ] > a.forEach(function (v) { ... console.log(v); ... }); 1 2 3 ~~~ 若想使用高级的编辑模式,设置环境变量 `NODE_NO_READLINE=1` 后运行 node。这将在允许你在可以使用 `rlwrap` 的终端上,启动高级的 REPL 模式 (the main and debugger REPL)。 例如,您可以将下列代码加入到您的 bashrc 文件: ~~~ alias node="env NODE_NO_READLINE=1 rlwrap node" ~~~ ### repl.start(options) 启动并返回一个 `REPLServer` 实例。接受一个包含如下内容的 "options" 对象: - `prompt` - 所有输入输出的提示符。默认是 `>` . - `input` - 监听的可读流。默认指向标准输入流 `process.stdin`。 - `output` - 用来输出数据的可写流。默认指向标准输出流 `process.stdout`。 - `terminal` - 如果 `stream` 应该被当做 TTY 来对待并且有 ANSI/VT100 转义时,则传 `true`。 默认使用 `output` 实例的 `isTTY`来检查。 - `eval` - 用来对每一行进行求值的函数。 默认为`eval()`的一个异步包装函数。下面给出一个自定义`eval`的例子。 - `useColors` - 一个布尔值,表明了`writer`函数是否会输出颜色。如果设定了一个不同的`writer`函数,那么这不会产生任何影响。默认为repl的`terminal`值。 - `useGlobal` - 如果设定为`true`,那么repl就会使用`global`对象而不是在一个独立环境里运行脚本。默认为`false`。 - `ignoreUndefined` - 如果设定为`true`,那么repl将不会输出未定义命令的返回值。默认为`false`。 - `writer` - 每一个命令被求值时都会调用此函数,而该函数会返回显示的格式(包括颜色)。默认为`util.inspect`。 `util.inspect`. 你可以使用你自己的`eval`函数,只有它有如下的签名: ~~~ function eval(cmd, context, filename, callback) { callback(null, result); } ~~~ 多个REPL可以在同一个运行的节点实例上打开。它们共享同一个global对象,但分别有各自的I/O。 以下是通过标准输入流(stdin)、Unix socket 以及 TCP socket 三种情况来启动 REPL 的例子: ~~~ net.createServer(function (socket) { connections += 1; repl.start({ prompt: "node via TCP socket> ", input: socket, output: socket }).on('exit', function() { socket.end(); }); }).listen(5001); ~~~ 从命令行运行该程序,将会从标准输入流启动 REPL 模式。 其他的 REPL 客户端也可以通过 Unix socket 或者 TCP socket 连接。 `telnet` 常用于连接 TCP sockets,而 `socat` 则可以同时用来连接 Unix 和 TCP sockets。 通过从一个Unix的套接字服务器而不是stdin来启动REPL, 你可以连接到一个长久运行的node进程而不不需要重启。 一个在`net.Server`和`net.Socket`实例上运行的"全功能"(`terminal`)REPL的例子可以查看这里: [https://gist.github.com/2209310](https://gist.github.com/2209310) 一个在`curl(1)`上运行的REPL实例的例子可以查看这里: [https://gist.github.com/2053342](https://gist.github.com/2053342) ### 事件: 'exit' `function () {}` 当用户通过任意预定义的方式退出REPL,该事件被分发。比如,在repl里输入`.exit`,按Ctrl+C两次来发送SIGINT信号,或者在`input`流上按Ctrl+D来发送"end"。 监听 `exit` 事件的例子: ~~~ r.on('exit', function () { console.log('从 REPL 得到 "exit" 事件!'); process.exit(); }); ~~~ ### 事件: 'reset' `function (context) {}` 当REPL的上下文被重置时,该事件被分发。当你打`.clear`命令时这种情况就会发生。如果你以`{ useGlobal: true }`来启动repl,那么这个事件就永远不会被分发。 监听`reset`的例子: ~~~ // 当一个新的上下文被创建时,扩充这个上下文。 r.on('reset', function (context) { console.log('repl有一个新的上下文'); someExtension.extend(context); }); ~~~ ### REPL 特性 在REPL里,Control+D会退出。可以输入多行表达式。对于全局变量和本地变量都支持自动缩进。 特殊变量 `_` (下划线)储存了上一个表达式的结果。 ~~~ > [ "a", "b", "c" ] [ 'a', 'b', 'c' ] > _.length 3 > _ += 1 4 ~~~ REPL提供了访问global域里所有变量的权限。通过将一个变量赋值给与每一个`REPLServer`关联的`context`对象,你可以显式地将一个变量暴露给REPL。例如: ~~~ repl.start("> ").context.m = msg; ~~~ 在`context`对象里的东西,会在REPL以本地变量的形式出现。 ~~~ mjr:~$ node repl_test.js > m 'message' ~~~ 有几个特殊的REPL命令: - `.break` - 当你输入一个多行表达式时,有时你走神了或者你不想完成这个表达式了。`.break`让你可以重头再来。 - `.clear` - 重置`context`对象为一个空对象,并且清除所有的多行表达式。 - `.exit` - 关闭I/O流,使得REPL退出。 - `.help` - 显示这个特殊命令的列表。 - `.save` - 将当前的REPL会话保存到一个文件 > .save ./file/to/save.js - `.load` - 将一个文件装载到当前的REPL会话。 > .load ./file/to/load.js 下面的组合键在REPL中有以下效果: - `<ctrl>C` - 与`.break`关键字类似。终止正在执行的命令。在一个空行连按两次会强制退出。 - `<ctrl>D` - 与`.exit`关键字类似。