文档章节

nodejs里的repl

i5ting
 i5ting
发布于 2015/08/06 09:40
字数 1069
阅读 1335
收藏 10

nodejs里的repl

输入图片说明

什么是REPL?

REPL(Read-Eval-Print Loop) 中文的话有翻译成“交互式解释器”或“交互式编程环境”的。不过我觉得不用翻译,直接REPL就好了,这样的术语,翻译成中文后,读者更难理解。下面是对 REPL 的解释:

A Read-Eval-Print-Loop (REPL) is available both as a standalone program and easily includable in other programs. REPL provides a way to interactively run JavaScript and see the results. It can be used for debugging, testing, or just trying things out.

交互式解释器(REPL)既可以作为一个独立的程序运行,也可以很容易地包含在其他程序中作为整体程序的一部分使用。REPL为运行JavaScript脚本与查看运行结果提供了一种交互方式,通常REPL交互方式可以用于调试、测试以及试验某种想法。

基本上所有的脚本语言有REPL的。

Nodejs的REPL

https://iojs.org/api/repl.html

  • 稳定等级 Stability: 2 - Stable

A Read-Eval-Print-Loop (REPL) is available both as a standalone program and easily includable in other programs. The REPL provides a way to interactively run JavaScript and see the results. It can be used for debugging, testing, or just trying things out.

以上的意思是说node有一个很好的repl环境,可以用于调试、测试或尝试其他更有意思的东西

最简单的例子

// repl_test.js
var repl = require("repl"),
    msg = "message";

repl.start("> ").context.m = msg;

然后

➜  moa-console git:(master) ✗ node repl_test.js 
> m
'message'
> 

实例

如果用过rails,一定很喜欢rails console,它可以直接调用AR里的各种方法,非常简单的就可以测试对db的各种操作。那么作为一个nodejs开放,是否也可以实现一样的功能呢?

需求

  • 加载app/models下的所有mongoose模型
  • .list命令打印出所有的可用实体
  • 执行User.find({},function(err,doc){console.log(doc)})可以查出具体内容

加载模型为global对象

var models = requireDirectory(module, model_path);

console.log('Available Entity: ');
// 此处没有做递归,可能有bug
for(var i in models){
  var name = Inflector.camelize(i);
  console.log('  - ' + name);
  global[name] = models[i];
}

这样就可以在repl里使用,这些对象了

比如user.js会变成User类,这里有一个小机器,即

Inflector.camelize(i)

让单词的首字母大写

测试

所有的global的对象都会在repl的上下文里,所以可以直接执行

Moa> User.find({},function(err,doc){console.log(doc)})
undefined
Moa> [ { _id: 55c19fd43dac1deb08c43888,
    username: '12',
    password: '2',
    avatar: '23',
    phone_number: '23',
    address: '',
    __v: 0 },
  { _id: 55c19fde3dac1deb08c43889,
    username: 'sang',
    password: '000000',
    avatar: '',
    phone_number: '',
    address: '',
    __v: 0 } ]

undefined
Moa> 

讨厌的点

  • 不能分行
  • 回调太痛苦

需要给mongoose扩展一些Sync方法,不然测试起来会死人的。

.list命令打印出所有的可用实体

repl.commands['.list'] = {
  help: 'Show Available Entity',
  action: function() {
    var models = requireDirectory(module, model_path);

    console.log('Available Entity: ');
    // 此处没有做递归,可能有bug
    for(var i in models){
      var name = Inflector.camelize(i);
      console.log('  - ' + name);
      global[name] = models[i];
    }
  
    repl.displayPrompt();
  }
};

这个实际和上面的代码是一样,唯一不一样的是repl.command定义自己的命令

在repl里内置.help命令

Moa> .help
.break	Sometimes you get stuck, this gets you out
.clear	Break, and also clear the local context
.exit	Exit the repl
.help	Show repl options
.history	Show the history
.list	Show Available Entity
.load	Load JS from a file into the REPL session
.save	Save all evaluated commands in this REPL session to a file
Moa> 

上面定义.list命令,所以才有,这样大家可以自己扩展自己想要实现的命令

使用历史记录

历史记录即可以向上,向下翻查历史命令

repl有具体实现,参见 https://github.com/tmpvar/repl.history

原理也很简单

function history(repl, file) {

  try {
    var stat = fs.statSync(file);
    repl.rli.history = fs.readFileSync(file, 'utf-8').split('\n').reverse();
    repl.rli.history.shift();
    repl.rli.historyIndex = -1;
  } catch (e) {}

  var fd = fs.openSync(file, 'a'),
    reval = repl.eval;

  repl.rli.addListener('line', function(code) {
    if (code && code !== '.history') {
      fs.write(fd, code + '\n');
    } else {
      repl.rli.historyIndex++;
      repl.rli.history.pop();
    }
  });

  process.on('exit', function() {
    fs.closeSync(fd);
  });

  repl.commands['.history'] = {
    help: 'Show the history',
    action: function() {
      var out = [];
      repl.rli.history.forEach(function(v, k) {
        out.push(v);
      });
      repl.outputStream.write(out.reverse().join('\n') + '\n');
      repl.displayPrompt();
    }
  };
}

对行内内容进行特殊处理

repl.rli.addListener('line', function(code) {
  if (code && code !== '.history') {
    fs.write(fd, code + '\n');
  } else {
    repl.rli.historyIndex++;
    repl.rli.history.pop();
  }
});

这样就可以干很多很多坏事了

代码

https://github.com/moajs/moa-console

官方推荐2个小例子

全文完

欢迎关注我的公众号【node全栈】

node全栈.png

© 著作权归作者所有

i5ting

i5ting

粉丝 199
博文 68
码字总数 98509
作品 3
东城
私信 提问
加载中

评论(1)

mikite
mikite
0
从 global.console 看 Node.js 中的作用域

原作者:洗影 最近有小伙伴来问我,为什么这段代码不起作用? Node.js 中的 Node.js 中存在一个全局对象 (文档),类似浏览器里的 。挂载在上面的变量,可以被所有模块共享,并且站在作用域...

_朴灵_
2018/05/14
0
0
Node.js 启动方式:一道关于全局变量的题目引发的思考

原文链接:https://xcoder.in/2015/11/26/a-js-problem-about-global/ 原题 题目是这样的。 上题由我们亲爱的小龙童鞋发现并在我们的 901 群里提问的。 经过 然后有下面的小对话。 小龙:你们...

死月
09/29
0
0
Node.js 6.9.3 和 4.7.1 (LTS) 版本发布

Node.js 6.9.3 (LTS) 和 4.7.1 (LTS) 版本发布了。 更新内容: Node.js 6.9.3 显著变化: 构建:共享库现支持为 AIX 构建 deps: npm:升级到3.10.10 V8:通过计算属性解构箭头函数参数不再抛...

王练
2017/01/04
2.1K
4
nodejs终端的坑--新手向

npm install -g react-tools 命令无法在node.js终端里运行, 并报错npm should be run outside of the node repl, in your normal shell, 将此命令用cmd运行,,成功运行,,nodejs只能运行js代码...

沐日starTree
2016/02/23
79
0
Node.js 11.1.0 发布,服务器端的 JavaScript 运行环境

Node.js v11.1.0 已发布,这是针对 v11.0.0 的修复和改进版本,更新包括: deps Updated ICU to 63.1. #23715 repl Top-level for-await-of is now supported in the REPL. #23841 timers F......

王练
2018/11/03
666
3

没有更多内容

加载失败,请刷新页面

加载更多

MVC Linux下开发及部署

linux使用的是 Ubuntu 64 位 18.04.2 LTS 首先复制C:\Program Files (x86)\Embarcadero\Studio\20.0\PAServer 下 LinuxPAServer20.0.tar.gz 到 linux 目录下 运行链接编译程序 delphi环境配置......

苏兴迎
今天
9
0
3.控件及其属性

1.文本 2.按钮

横着走的螃蟹
今天
7
0
安装Genymotion模拟器慢的解决方案

第一步点击下载, C:\Users\Administrator\AppData\Local\Genymobile\genymotion.log 中搜索 ova 会发现这个文件 使用迅雷下载即可. 在 虚拟机中导入这个.ova 文件 即可安装...

chenhongjiang
今天
5
0
4. 彤哥说netty系列之Java NIO实现群聊(自己跟自己聊上瘾了)

你好,我是彤哥,本篇是netty系列的第四篇。 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识。 简介 上一章我们一起学习了Java中的BIO/NIO/AIO的故事,本章将带着大家一起使用纯纯的N...

彤哥读源码
今天
7
0
如何把握好面试的最后一问 ?

如何把握好面试的最后一问 ? 你有没有听过这句话 “ 你还有什么问题想问我的吗? ” 如何把握好面试的最后一问 ? 要积极稳妥,切莫减分、丢分、扣分。比如,你提问的问题很傻很天真,比如你提...

编程三分钟
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部