Node.js核心模塊readline

Node.js中文網(wǎng)的 v6.10.3 文檔提供了readline模塊,可以從可讀流(process.stdin)讀取數(shù)據(jù),Node.js的v6.10.3 版本是長期支持版本,而readline也是比較穩(wěn)定的API了,下面詳細描述一下readline的官方API;之前寫了一個從酷狗音樂爬取音樂歌曲的爬蟲腳本,但是每次都要從酷狗官網(wǎng)查找歌手的詳細地址,現(xiàn)在可以直接可以使用readline模塊從命令行窗口讀取我們要查找的歌手名稱,然后進行拼接處理。

1. <code>require(‘readline’)</code>模塊提供了一個接口,用于從可讀流中(process.stdin)中讀取數(shù)據(jù),每次讀取一行,由于readline不是Node.js的全局模塊變量,所以需要引入readline模塊。
require ('readline);
  • 下面是官方給出的readline基本用法:
const readline=require('readline');
const rl=readline.createInterface({
    input:process.stdin,
    output:process.stdout
});
rl.question('你覺得Node.js中文網(wǎng)怎么樣?',(answer)=>{
    //對答案進行處理
    console.log(`多謝你的反饋:${answer}`);
    rl.close();
});
  • 運行上述代碼并輸入你想輸入的評價,就可以直接可以輸出具體的結(jié)果,詳細如下:
readline模塊
  • 注意,當(dāng)調(diào)用代碼時候,Node.js不會終止,只有realine.createInterface被關(guān)閉;因為接口在等待 input 流中要被接收的數(shù)據(jù)。
2. Interface類:readline.Interface類的實例都是使用readline.createInterface()方法構(gòu)造的。每個實例都關(guān)聯(lián)著一個input可讀流和一個output可寫流。output流用于用戶輸入打印顯示,output流數(shù)據(jù)從input流中讀取。
  • ‘close’事件:當(dāng)以下之一發(fā)生時,觸發(fā)'close'事件:
    • rl.close()方法被調(diào)用,且readline.Interface實例已經(jīng)撤回對input流和output流的控制。
    • input流收到end事件。
    • input流收到表示結(jié)束傳輸?shù)?lt;ctrl+D>。
    • input流收到SIGINT的<ctrl+C>,且readline.interface實例上沒有注冊SIGINT事件監(jiān)聽器。
    • 監(jiān)聽器函數(shù)不接受任何參數(shù),當(dāng)'close'事件被觸發(fā)時,readline.Interface實例應(yīng)當(dāng)被視為結(jié)束。
  • ‘line’事件:每當(dāng)input流收到行結(jié)束符(\n ,\r或者\n\r時觸發(fā)‘line事件。通常發(fā)生在用戶按下<enter>或<return>鍵)
    • 監(jiān)聽器函數(shù)被調(diào)用時會帶上一個包含接收哪一行輸入的字符,實例如下包括運行結(jié)果。
const readline=require('readline');
const rl=readline.createInterface({
    input:process.stdin,
    output:process.stdout
});
rl.on('line',(input)=>{
    console.log(`接收到: ${input}`);
    rl.close();
});
line事件
  • 'pause'事件:當(dāng)以下之一事件發(fā)生時觸發(fā)'pause'事件:
    • input 流暫停。
    • input 流不是暫停的,且收到SIGONT事件。
    • 監(jiān)聽函數(shù)被調(diào)用時不傳入任何參數(shù)。
    • 例子:
rl.on('pause',()=>{
  console,log('Readline 被暫停。');
});
  • ‘resume’事件:每當(dāng)input流被恢復(fù)時觸發(fā)'resume'事件。監(jiān)聽器函數(shù)被調(diào)用時不傳入任何參數(shù)。
    • 實例如下:
rl.on('resume',()=>{
   console.log('Readline 被恢復(fù)。');
});
  • ‘SIGCONT’事件:
    • 當(dāng)一個Node.js進程使用<ctrl +z>(也就是SIGSTP)移入后臺之后再使用fg(1)移回前臺時,觸發(fā)'SIGCONT'事件。
    • 如果input流在SIGSTP請求之前被暫停,則事件不會被觸發(fā)。
    • 監(jiān)聽器函數(shù)被調(diào)用時不傳任何參數(shù)。
    • 例子(注意,Windows系統(tǒng)不支持‘SIGCONF’事件):
rl.on('SIGCONF',()=>{
   //'prompt'會自動恢復(fù)流
   rl.prompt();
});
  • ‘SIGINT’事件:每當(dāng)input流接收到一個<ctrl + C>輸入(通常被稱為SIGINT)時,觸發(fā)‘SIGINT’事件,當(dāng)input流接收到一個SIGINT時,如果沒有注冊‘SIGINT’事件監(jiān)聽器,則‘pause’事件會被觸發(fā)。
    • 監(jiān)聽器函數(shù)被調(diào)用時不傳入任何參數(shù),例子如下。
rl.on('SIGCONF',()=>{
  rl.question('確定要退出嗎?',(answer)=>{
      if(answer.match(/^y(es)?$/i))
          rl.pause();
  });
});
  • 'SIGSTP'事件:每當(dāng)input流接收到一個<ctrl+z>輸入(通常被稱為SIGSTP)時,觸發(fā)‘SIGSTP’事件。當(dāng)input流接收到一個SIGSTP時,如果沒有注冊‘SIGSTP’事件監(jiān)聽器,則Node.js進程會被發(fā)送到后臺。
    • 當(dāng)程序使用fg(1)恢復(fù)時,‘pause’和‘SIGCONF’事件會被觸發(fā)。這可被用來恢復(fù)input流。
    • 如果input流在進程被發(fā)送到后臺之前被暫停,則‘pause’和‘SIGCONF’事件不會被觸發(fā)。
    • 實例如下所示(注意,Windows系統(tǒng)不支持‘SIGSTP’):
rl.on('SIGCONF',()=>{
  //這會重寫SOGSTP,且防止程序進入后臺
  console.log('捕獲SIGSTP');
});
  • rl.close():rl.close()方法會關(guān)閉readline.Interface實例,且撤回對input和output流的控制。但調(diào)用時,close事件會被觸發(fā)。

  • rl.pause():rl.pause()方法會暫停input流,且稍后需要時可被恢復(fù)。調(diào)用rl.pause()不會立刻暫停其他事件(包括‘line’)被readline.Interface實例觸發(fā)。

  • rl.prompt([preserveCursor]):preserveCursor(boolean)如果為true,則阻止光標(biāo)落點被設(shè)置為0。

    • rl.prompt()方法會在output流中新的一行寫入readlin.Interface實例配置后的prompt,用于為用戶提供一個可供輸入新的位置。
    • 當(dāng)被調(diào)用時,如果input流已經(jīng)被暫停,則rl.prompt()會回復(fù)input流。
    • 如果readline.Interface被創(chuàng)建時ouput被設(shè)為null或undefined,則提示不會被寫入。
  • rl.question(query,callback):

    • query(String)一個在提示符之前、要寫入output的敘述或提問。
    • callback(Function)一個回調(diào)函數(shù),它會被調(diào)用并帶上用戶響應(yīng)query的輸入。
    • rl.question()方法通過寫入output來展示query,并等待用戶提供到input的輸入,然后調(diào)用callback函數(shù)并傳入提供的輸入作為第一個參數(shù)。
    • 當(dāng)被調(diào)用,如果input流已被暫停,則rl.question()會恢復(fù)input流。
    • 如果readline.Interface被創(chuàng)建時,output被設(shè)為null或undefined,則query不會被寫入。
    • 實例如下所示(注意,傳入的rl.question()的callback函數(shù)不支持遵循一個Error對象會Null作為第一個參數(shù)的標(biāo)準(zhǔn)模式。callback被調(diào)用時只帶上提供的答案作為唯一參數(shù)):
rl.question('你最喜歡的食物是什么?',(answer)=>{
  console.log(`你最喜歡的食物是 ${answer}`);
});
  • rl.resume():如果input流已被暫停,則rl.resume()方法會恢復(fù)input流。

  • rl.setPrompt(prompt):

    • prompt(String):rl.setPrompt()方法用于設(shè)置每當(dāng)rl.prompt()被調(diào)用時要被寫入output的提示。
  • rl.write(data[,key]):

    • data(String):

    • key(Object):

      • ctrl (boolean)如果為true則表示<ctrl>鍵
      • meta (boolean)如果為true則表示<Meat>鍵
      • shift (boolean)如果為true則表示<shift>鍵
      • name (String)一個按鍵的名稱
    • rl.write()方法會把data或一個由Key指定的按鍵序列寫到output。只有當(dāng)output是一個TTY文本終端時,Key參數(shù)才被支持。

    • 如果指定了key,則data會被忽略。當(dāng)被調(diào)用時,如果input流已經(jīng)暫停,則rl.write()會恢復(fù)input流。

    • 如果readline.Interface被創(chuàng)建時output被設(shè)置為null或undefined,則data和key不會寫入。

    • 例子如下(注意,rl.write()方法會寫入數(shù)據(jù)到readline接口的input,仿佛他是用戶提供的):

rl.write('刪除這個!');
//模擬ctrl+u刪除寫入的前一行
rl.write(null,{
  ctrl:true,
  name:'u'
});
  • readline.clearLine(stream,dir):
    • stream(Writable):
    • dir(number):
      • -1 光標(biāo)左邊
      • 1-光標(biāo)右邊
      • 0 -整行
    • readline.clearLine()方法會以dir指定的方向清除給定的TTY流當(dāng)前行。
  • readline.clearScreenDown(Strem):
    • stream(writable)
    • readline.clearScreenDown()方法會從光標(biāo)的當(dāng)前位置向下清除給定TTY流。
  • readline.createInterface(options):
    • options:(object)
      • input(Readable)要監(jiān)聽的可讀流。該選項是必須的。
      • output(Writable)要寫入逐行讀取數(shù)據(jù)的可寫流。
      • completer(Function):一個可選的函數(shù),用于Tab自動補全。
      • Terminal(boolean):如果input和output應(yīng)被當(dāng)做一個tty,且要寫入ANSI、VT100轉(zhuǎn)換的代碼,則設(shè)置為true;默認實例化時在output流上檢查isTTY。
      • historySize(number):保留的歷時行數(shù)的最大數(shù)量,設(shè)為0課禁用歷史記錄。默認為30.該選項只有terminal被用戶或內(nèi)部output設(shè)為true時才有意義,否則歷史緩存機制不會被初始化。
      • prompt -要使用的提示字符串。默認為'>'.
      • crlfDelay(number):如果\r與\n之間的延遲超過crlfDelay毫秒,則\r與\n都會當(dāng)做換行分隔符。默認為100毫秒。crlfDelay的范圍為[100,2000].
    • readline.createInterface()方法創(chuàng)建一個新的readline.Intreface實例,例子如下:
const readline=require('readline');
const rl=readline.createInterface({
  input:process.stdin,
  output:process.stdout
});
+ 一旦readline.Interface實例被創(chuàng)建,最常見的就是監(jiān)聽‘line’事件:
rl.on('line',(line)=>{
  console.log(`接收到:${line}`);
});
+ 如果該實例的terminal為true,則若它定義了一個output.columns屬性則output流會獲得最佳兼容性,且如果或當(dāng)列發(fā)生變化時,output上觸發(fā)一個'resize'事件(當(dāng)它為一個TTY時,process.stdout會自動處理這個)。
+ completer函數(shù)使用:當(dāng)被調(diào)用時,用戶輸入的當(dāng)前行會被提供給completer函數(shù),并返回一個包含以下兩個條目的數(shù)組:
   + 一個包含自動補全輸入的數(shù)組。
   + 用于匹配的字符串。
   + 例如:[[substr1,substr2,...],originalsubstring]。
function completer(line){
  const completions='.help .error .quit  .q'.split(' ');
  const hits=completions.filter((c)=>{return c.indexOf(line)==0});
  //如果沒匹配到則展示到=全部補全
  return  [hits.length?hits:completions,line];
}
   + 如果completer函數(shù)結(jié)束兩個參數(shù),則可被異步地調(diào)用。
function completer(linePartial,callback){
  callback(null,[['123'],linePartial]);
}
  • readline.curorTo(stream,x,y):
    • stream(writable):
    • x (number):
    • y(number):
    • readline.cursorTo()方法會移動光標(biāo)到指定的TTY stream中指定的位置。
  • readline.emitKeypressEvent(stream[,interface):
    • stream(Readable):
    • interface(readline.Interface):
    • readline.emitKeypressEvents()方法是給定的可寫流stream相應(yīng)接收到的輸入觸發(fā)‘keypress’事件。
    • 可選的interface指定了一個readline.Interface實例,用于當(dāng)自動補全被禁用時檢測到復(fù)制黏貼輸入。
    • 如果stream是一個TTY,則它必須為原始模式。
readline.emitKeypressEvents(process.stdin);
if(process.stdin.isTTY)
  process.stdin.setRawMode(true);
  • readline.moveCursor(stream,dx,xy):
    • stream:(writable):
    • dx:(number):
    • dy(Number):
    • readline.moveCursor()方法移動光標(biāo)到給定的TTY stream中相對當(dāng)前的位置。
3.例子:簡單的命令行界面
  • 例子,使用readline.Interface類實現(xiàn)一個簡單的命令行界面:
const readline=require('readline');
const rl=readline.createInterface({
  input:process.stdin,
  output:process.stdout,
  prompt:'請輸入>'
});
rl.prompt();
rl.on('line',(line)=>{
  switch(line.trim()){
    case 'hello':
      console.log('world');break;
    default:
      console.log(`你輸入的是:${line.trim()}`);break;
  }
rl.prompt();
}).on('close',()=>{
  console.log('再見!');
  process.exit(0);
});
4.逐行讀取文件流:
  • 例子,從一個文件系統(tǒng)可讀流中每次一行地消耗輸入:
const readline=require('readline');
const fs=require('fs');
const rl=readline.createInterface({
  input:fs.createReadStream('sample.txt');
});
rl.on('line',(line)=>{
  console.log('文件的單行內(nèi)容:${line}');
});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評論 19 139
  • 終端和nodejs的io交互(io是input和output,輸入和輸出) 終端和io交互需要引入一個nodejs...
    東海虬髯客閱讀 355評論 0 0
  • https://nodejs.org/api/documentation.html 工具模塊 Assert 測試 ...
    KeKeMars閱讀 6,603評論 0 6
  • 本課重點:學(xué)習(xí)使用Node.js中的'readline'模塊實現(xiàn)終端的io交互功能,并衍生到web中靜態(tài)頁面上的i...
    瘋范兒閱讀 402評論 0 0
  • 個人入門學(xué)習(xí)用筆記、不過多作為參考依據(jù)。如有錯誤歡迎斧正 目錄 簡書好像不支持錨點、復(fù)制搜索(反正也是寫給我自己看...
    kirito_song閱讀 2,651評論 1 37

友情鏈接更多精彩內(nèi)容