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);
});
輸出:

