NodeJS用递归实现异步操作的链式调用,完成一个简易的命令行输入输出REPL交互接口
REPL —— Read-Eval-Print-Loop.
00.一门好的编程语言的必要条件
REPL并不是什么高大上的东西,简单的说就是一个从命令行程序,读取终端输入,处理,打印结果,如此循环。这是一门比较全面的编程语言的基础。
刚开始接触NodeJS,以为就是一个服务端Js,但学习了一段时间之后才感受到它的强大和魅力。如果说Java是编程游戏里一个喜欢循规蹈矩的古板选手,JavaScript就是一个天马行空的飘逸选手。刚开始转型异步编程非常不习惯,慢慢的懂得,异步编程,是一种思维。
01.依葫芦画不出瓢
一个命令行读取输入,处理的程序,Java可以写一个while循环来不停的用Scanner来readLine,但是如果模仿Java用JS就有点麻烦了,
var rl = require('readline');
while(true) {
rl.on('line',function(data){
//to deal data
});
}
这样很显然是不行滴,不过习惯了同步编程的猿们说不定会这样干,JavaScript的异步意味着非阻塞式的设计,不会因为等用户输入阻塞下一次循环。所以要告诉JavaScript在这一次处理完之后,再进行下一次读取(回调),那么问题来了,臭名昭著的Callback hell就有可能发生了。
10.如何正确画瓢,还要看起来舒服
解决方案1:使用async,co,q, promise等等机制来同步
解决方案2:对于一个REPL程序,逻辑很简单,如果实现一个链式调用的接口就好了,像这样:
read("var1", function(data){}).read("var2",function(data){})...
写原生代码比使用开源库更加容易调试,而且杀鸡焉用牛刀,不麻烦co这样的模块了,q 这种then()的链式调用差强人意,想做什么就直接 .xx().xx()更直观。
11.银弹
用起来简单的东西,背后一定是用更复杂或更精巧的方式掩盖了其真实的复杂度。
repl.js
var readline = require('readline'); //非常好用的Node自带库 var rl = null; //Singleton
var questions = []; //处理队列
var cursor = 0; //游标 function dealQuestions(_self) { //递归处理队列中的读取请求
if(cursor >= questions.length) {
cursor = 0;questions = [];
rl.close();
rl = null;
return _self;
} rl.question(questions[cursor].question, function (data) {
questions[cursor].deal(data);
++cursor;
dealQuestions(); //读取处理完毕回调
});
} var easyREPL = function(){
if(rl == null) { //初始化模块
rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
}
return this;
}; /**
* @description : a liner api to get console input
* @param : question to ask , function to deal answer
* */
easyREPL.prototype.question = function(question,dealAnswer){
easyREPL();
rl.prompt();
var _self = this; //保存this指针
questions.push({question:question,deal:dealAnswer}); //加入处理队列
if(questions.length == 1) {
dealQuestions(_self);
}
return this; //实现链式调用的关键:返回this
}; exports.REPL_Mode = easyREPL;
测试代码:test.js
var easyREPL = require("./repl").REPL_Mode; var test = new easyREPL(); /* comment following codes to test command mode */
test.question("Input name:" , function(data) {
console.log("Get name:"+data);
}).question("Input password:",function(data){
console.log("Get password:"+data);
}).question("Input Email:",function(data){
console.log("Get email:"+data);
});
输出:
这是一个引子,NodeJS能做的事情太多了,另外还做了一个解析输入命令的程序,代码比这个多,但是不够精髓,还是不放了。
NodeJS用递归实现异步操作的链式调用,完成一个简易的命令行输入输出REPL交互接口的更多相关文章
- hasOwnProperty 递归 简单回调 链式调用
1.hasOwnProperty 函数的返回值为Boolean类型.如果对象object具有名称为propertyName的属性,则返回true,否则返回false. function Box(){ ...
- ES6 Promise 的链式调用
1.什么是Promise Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息. 2.对象的状态不受外界影响.Promise 对象代表一个异步操作,有三种状态: pending: 初始 ...
- 如何写 JS 的链式调用 ---》JS 设计模式《----方法的链式调用
1.以$ 函数为例.通常返回一个HTML元素或一个元素集合. 代码如下: function $(){ var elements = []; ;i<arguments.length;i++){ v ...
- 【Java】子类的链式调用
记录最近在项目设计中遇到的一个小问题. 前提:有这样两个POJO类,它们都可以通过链式调用的方式来设置其属性值,其中一个类继承了另一个类. 问题:通过链式调用,子类对象访问父类方法后,如何使返回对象仍 ...
- swift学习笔记之-可选链式调用
//可选链式调用 import UIKit /*可选链式调用(Optional Chaining) 1.在可选值上请求和调用该可选值的属性.方法及下标的方法,如果可选值有值,那么调用就会成功,返回可选 ...
- Swift2.1 语法指南——可空链式调用
原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...
- JavaScript设计模式——方法的链式调用
方法的链式调用: (function() { //私有类 function _$ (els) { this.elements = []; for(var i = 0, len = els.length ...
- jQuery的XX如何实现?——2.show与链式调用
往期回顾: jQuery的XX如何实现?——1.框架 -------------------------- 源码链接:内附实例代码 jQuery使用许久了,但是有一些API的实现实在想不通.于是抽空看 ...
- Swift-09-可空链式调用(Optional Chaining)
我对这个的理解就是:我们有可能会用到其他的属性或者方法,当我们在使用其他的时候,可以使用点语法去访问另一个的属性,这样的使用,就形成了链式访问. 可空链式调用是一种可以请求和调用属性.方法及下表的过程 ...
随机推荐
- 修改ie版本的注册表webbroswer
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Exp ...
- 今天用css做了一个QQ登录页面
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- javascript事件学习笔记
事件冒泡 并不是所有的事件都支持事件冒泡,比如submit ,focus,blur不支持事件冒泡,mouseover,mouseout虽然支持冒泡,但是一般不用,因为需要经常计算元素的位置,消耗比较大 ...
- Android 线程Thread的2种实现方法
在讲解之前有以下三点要说明: 1.在Android中有两种实现线程Thread的方法: ①扩展java.long.Thread类: ②实现Runnable()接口: 2.Thread类是线程类,它有两 ...
- Android OOM 解决方案
Out of Memory(内存溢出) 几乎是每个Android程序员都会遇到的事.在网上也能找到一大堆的解决方案,之前写过一篇<Android 内存溢出管理与测试>的博文.但感觉写得不是 ...
- Android 全屏相关操作
1.隐藏标题栏(titlebar) (1)在代码中隐藏标题栏 requestWindowFeature(Window.FEATURE_NO_TITLE); (2)在Manifest中Applicati ...
- js和jQuery创建元素和把元素插入到文档中所用的方法
js创建元素: document.createElement(" 创建的元素"); //“创建的元素”指:p ,h1,div,span........ js插入元素: docu ...
- Redis rdb文件CRC64校验算法 Java实现
查看RDB文件结构,发现最后的8字节是CRC64校验算得,从文件头开始直到8字节校验码前的FF结束码(含),经过CRC64校验计算发现,貌似最后的8字节是小端模式实现的. 参考redis的crc64实 ...
- HTML+CSS学习笔记(2) - 认识标签(1)
HTML+CSS学习笔记(2) - 认识标签(1) 1.语义化,让你的网页更好的被搜索引擎理解 标签的用途: 我们学习网页制作时,常常会听到一个词,语义化.那么什么叫做语义化呢,说的通俗点就是:明白每 ...
- XCode中的特殊快捷键图标
⌘——Command () ⌃ ——Control ⌥——Option (alt) ⇧——Shift ⇪——Caps Lock fn——功能键就是fn