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