Node.js v21.7.2 文件
- Node.js v21.7.2
- ► 目錄
-
► 索引
- 宣告測試
- 非同步內容追蹤
- 非同步掛鉤
- Buffer
- C++ 外掛程式
- 使用 Node-API 的 C/C++ 外掛程式
- C++ 嵌入式 API
- 子程序
- 叢集
- 命令列選項
- 主控台
- Corepack
- 加密
- 偵錯器
- 已棄用的 API
- 診斷頻道
- DNS
- 網域
- 錯誤
- 事件
- 檔案系統
- 全域變數
- HTTP
- HTTP/2
- HTTPS
- 檢查器
- 國際化
- 模組:CommonJS 模組
- 模組:ECMAScript 模組
- 模組:
node:module
API - 模組:套件
- 網路
- 作業系統
- 路徑
- 效能掛鉤
- 權限
- 程序
- Punycode
- 查詢字串
- Readline
- REPL
- 報告
- 單一可執行檔應用程式
- 串流
- 字串解碼器
- 測試執行器
- 計時器
- TLS/SSL
- 追蹤事件
- TTY
- UDP/資料報
- URL
- 公用程式
- V8
- VM
- WASI
- Web Crypto API
- Web Streams API
- 工作執行緒
- Zlib
- ► 其他版本
- ► 選項
Readline#
原始碼: lib/readline.js
node:readline
模組提供了一個介面,用於一次從 可讀取 串流(例如 process.stdin
)讀取資料。
若要使用基於承諾的 API
import * as readline from 'node:readline/promises';
const readline = require('node:readline/promises');
若要使用回呼和同步 API
import * as readline from 'node:readline';
const readline = require('node:readline');
以下簡單範例說明 node:readline
模組的基本用法。
import * as readline from 'node:readline/promises';
import { stdin as input, stdout as output } from 'node:process';
const rl = readline.createInterface({ input, output });
const answer = await rl.question('What do you think of Node.js? ');
console.log(`Thank you for your valuable feedback: ${answer}`);
rl.close();
const readline = require('node:readline');
const { stdin: input, stdout: output } = require('node:process');
const rl = readline.createInterface({ input, output });
rl.question('What do you think of Node.js? ', (answer) => {
// TODO: Log the answer in a database
console.log(`Thank you for your valuable feedback: ${answer}`);
rl.close();
});
呼叫此程式碼後,Node.js 應用程式不會終止,直到 readline.Interface
關閉,因為介面會等到在 input
串流中收到資料。
類別:InterfaceConstructor
#
InterfaceConstructor
類別的執行個體是使用 readlinePromises.createInterface()
或 readline.createInterface()
方法建構的。每個執行個體都與單一 input
可讀取 串流和單一 output
可寫入 串流關聯。output
串流用於列印使用者輸入的提示,而使用者輸入會到達 input
串流並從中讀取。
事件:'close'
#
在發生下列其中一項情況時,會發出 'close'
事件
- 呼叫
rl.close()
方法,且InterfaceConstructor
執行個體已放棄對input
和output
串流的控制; input
串流收到其'end'
事件;input
串流收到 Ctrl+D 以表示傳輸結束 (EOT);input
串流收到 Ctrl+C 以表示SIGINT
,且在InterfaceConstructor
執行個體上未註冊'SIGINT'
事件監聽器。
呼叫監聽器函式時不傳遞任何引數。
發出 'close'
事件後,InterfaceConstructor
實例便會完成。
事件:'line'
#
每當 input
串流收到換行輸入 (\n
、\r
或 \r\n
) 時,便會發出 'line'
事件。這通常會在使用者按下 Enter 或 Return 時發生。
如果從串流中讀取新資料,且該串流在沒有最後換行標記的情況下結束,也會發出 'line'
事件。
呼叫監聽器函式時,會傳遞包含單一行接收輸入的字串。
rl.on('line', (input) => {
console.log(`Received: ${input}`);
});
事件:'history'
#
每當歷史記錄陣列變更時,便會發出 'history'
事件。
呼叫監聽器函式時,會傳遞包含歷史記錄陣列的陣列。它會反映所有變更,包括新增行和因 historySize
和 removeHistoryDuplicates
而移除的行。
主要目的是讓監聽器保留歷史記錄。監聽器也有可能變更歷史記錄物件。這可能有助於防止某些行(例如密碼)加入歷史記錄。
rl.on('history', (history) => {
console.log(`Received: ${history}`);
});
事件:'pause'
#
在發生下列情況之一時,會發出 'pause'
事件
呼叫監聽器函式時不傳遞任何引數。
rl.on('pause', () => {
console.log('Readline paused.');
});
事件:'resume'
#
每當 input
串流恢復時,就會發出 'resume'
事件。
呼叫監聽器函式時不傳遞任何引數。
rl.on('resume', () => {
console.log('Readline resumed.');
});
事件:'SIGCONT'
#
當先前使用 Ctrl+Z (即 SIGTSTP
) 移至背景的 Node.js 程序,再使用 fg(1p)
移回前景時,會發出 'SIGCONT'
事件。
如果 input
串流在 SIGTSTP
要求之前暫停,則不會發出此事件。
呼叫監聽器函式時不會傳遞任何引數。
rl.on('SIGCONT', () => {
// `prompt` will automatically resume the stream
rl.prompt();
});
Windows 不支援 'SIGCONT'
事件。
事件:'SIGINT'
#
每當 input
串流收到 Ctrl+C 輸入(通常稱為 SIGINT
)時,就會發出 'SIGINT'
事件。如果當 input
串流收到 SIGINT
時,沒有註冊 'SIGINT'
事件監聽器,則會發出 'pause'
事件。
呼叫監聽器函式時不會傳遞任何引數。
rl.on('SIGINT', () => {
rl.question('Are you sure you want to exit? ', (answer) => {
if (answer.match(/^y(es)?$/i)) rl.pause();
});
});
事件:'SIGTSTP'
#
當 input
串流收到 Ctrl+Z 輸入(通常稱為 SIGTSTP
)時,就會發出 'SIGTSTP'
事件。如果當 input
串流收到 SIGTSTP
時,沒有註冊 'SIGTSTP'
事件監聽器,則會將 Node.js 程序傳送至背景。
當使用 fg(1p)
恢復程式時,會發出 'pause'
和 'SIGCONT'
事件。這些事件可用於恢復 input
串流。
如果在程序送至背景之前暫停輸入,則不會發出 'pause'
和 'SIGCONT'
事件。
呼叫監聽器函式時不會傳遞任何引數。
rl.on('SIGTSTP', () => {
// This will override SIGTSTP and prevent the program from going to the
// background.
console.log('Caught SIGTSTP.');
});
Windows 不支援 'SIGTSTP'
事件。
rl.close()
#
rl.close()
方法會關閉 InterfaceConstructor
執行個體,並放棄對 input
和 output
串流的控制權。呼叫時,會發出 'close'
事件。
呼叫 rl.close()
並不會立即停止 InterfaceConstructor
執行個體發出其他事件(包括 'line'
)。
rl.pause()
#
rl.pause()
方法會暫停 input
串流,讓它在必要時可以繼續。
呼叫 rl.pause()
並不會立即停止 InterfaceConstructor
執行個體發出其他事件(包括 'line'
)。
rl.prompt([preserveCursor])
#
preserveCursor
<boolean> 如果為true
,會防止游標位置重設為0
。
rl.prompt()
方法會將 InterfaceConstructor
執行個體設定的 prompt
寫入 output
中的新行,以提供使用者新的輸入位置。
呼叫時,rl.prompt()
會在 input
串流暫停時繼續串流。
如果 InterfaceConstructor
是使用設定為 null
或 undefined
的 output
建立的,則不會寫入提示。
rl.resume()
#
rl.resume()
方法會在 input
串流暫停時繼續串流。
rl.setPrompt(prompt)
#
prompt
<字串>
rl.setPrompt()
方法會設定提示字串,當呼叫 rl.prompt()
時,會寫入 output
。
rl.getPrompt()
#
- 傳回:<字串> 目前的提示字串
rl.getPrompt()
方法會傳回 rl.prompt()
目前使用的提示字串。
rl.write(data[, key])
#
rl.write()
方法會將 data
或由 key
識別的按鍵順序寫入 output
。只有當 output
是 TTY 文字終端機時,才支援 key
參數。請參閱 TTY 按鍵繫結 以取得按鍵組合清單。
如果指定 key
,則會忽略 data
。
呼叫時,rl.write()
會在暫停後繼續 input
串流。
如果 InterfaceConstructor
是使用設定為 null
或 undefined
的 output
所建立,則不會寫入 data
和 key
。
rl.write('Delete this!');
// Simulate Ctrl+U to delete the line written previously
rl.write(null, { ctrl: true, name: 'u' });
rl.write()
方法會將資料寫入 readline
Interface
的 input
,就像使用者提供的資料一樣。
rl[Symbol.asyncIterator]()
#
建立一個 AsyncIterator
物件,以字串形式逐行迭代輸入串流。此方法允許透過 for await...of
迴圈非同步迭代 InterfaceConstructor
物件。
輸入串流中的錯誤不會轉送。
如果迴圈以 break
、throw
或 return
終止,將會呼叫 rl.close()
。換句話說,迭代 InterfaceConstructor
永遠會完整使用輸入串流。
效能無法與傳統的 'line'
事件 API 相提並論。對於效能敏感的應用程式,請改用 'line'
。
async function processLineByLine() {
const rl = readline.createInterface({
// ...
});
for await (const line of rl) {
// Each line in the readline input will be successively available here as
// `line`.
}
}
readline.createInterface()
呼叫後,將開始使用輸入串流。在建立介面和非同步迭代之間進行非同步操作可能會導致遺漏行。
rl.line
#
節點目前處理中的輸入資料。
這可在從 TTY 串流收集輸入時使用,以在發出 `line` 事件之前,擷取迄今已處理的目前值。一旦發出 `line` 事件,此屬性將會是空字串。
請注意,如果沒有同時控制 `rl.cursor`,在執行個體執行期間修改值可能會造成意外後果。
如果沒有使用 TTY 串流作為輸入,請使用 `'line'` 事件。
一個可能的用例如下
const values = ['lorem ipsum', 'dolor sit amet'];
const rl = readline.createInterface(process.stdin);
const showResults = debounce(() => {
console.log(
'\n',
values.filter((val) => val.startsWith(rl.line)).join(' '),
);
}, 300);
process.stdin.on('keypress', (c, k) => {
showResults();
});
rl.cursor
#
相對於 `rl.line` 的游標位置。
這會追蹤從 TTY 串流讀取輸入時,目前游標在輸入字串中的位置。游標位置會決定在處理輸入時,輸入字串中將修改的部分,以及終端插入符號將呈現的欄位。
rl.getCursorPos()
#
傳回游標相對於輸入提示字串的實際位置。計算時會包含長輸入(換行)字串,以及多行提示。
Promises API#
類別:readlinePromises.Interface
#
readlinePromises.Interface
類別的執行個體是使用 readlinePromises.createInterface()
方法建構的。每個執行個體都與單一 input
可讀取 串流和單一 output
可寫入 串流關聯。output
串流用於列印使用者輸入的提示,而使用者輸入會傳送到 input
串流並從中讀取。
rl.question(query[, options])
#
query
<string> 要寫入output
的陳述或查詢,附加在提示之前。options
<Object>signal
<AbortSignal> 選擇性地允許使用AbortSignal
取消question()
。
- 傳回:<Promise> Promise,在使用者輸入回應
query
後會以使用者的輸入兌現。
rl.question()
方法透過將 query
寫入 output
來顯示,等待使用者在 input
上提供輸入,然後呼叫 callback
函式,並將提供的輸入作為第一個引數傳遞。
呼叫時,如果 input
串流已暫停,rl.question()
會繼續串流。
如果 readlinePromises.Interface
是使用設定為 null
或 undefined
的 output
建立的,則不會寫入 query
。
如果在 rl.close()
之後呼叫問題,則會傳回一個遭拒絕的承諾。
範例用法
const answer = await rl.question('What is your favorite food? ');
console.log(`Oh, so your favorite food is ${answer}`);
使用 AbortSignal
取消問題。
const signal = AbortSignal.timeout(10_000);
signal.addEventListener('abort', () => {
console.log('The food question timed out');
}, { once: true });
const answer = await rl.question('What is your favorite food? ', { signal });
console.log(`Oh, so your favorite food is ${answer}`);
類別:readlinePromises.Readline
#
new readlinePromises.Readline(stream[, options])
#
stream
<stream.Writable> TTY 串流。options
<Object>autoCommit
<boolean> 如果為true
,則不需要呼叫rl.commit()
。
rl.clearLine(dir)
#
dir
<integer>-1
:從游標向左1
:從游標向右0
:整行
- 傳回:這個
rl.clearLine()
方法會將清除與指定 dir
識別的方向相關聯的 stream
的目前行動作新增至待處理動作的內部清單。呼叫 rl.commit()
以查看此方法的效果,除非將 autoCommit: true
傳遞給建構函式。
rl.clearScreenDown()
#
- 傳回:這個
rl.clearScreenDown()
方法會將清除游標目前位置以下的關聯串流的動作加入到待處理動作的內部清單中。呼叫 rl.commit()
以查看此方法的效果,除非建構函式傳遞了 autoCommit: true
。
rl.commit()
#
- 傳回: <Promise>
rl.commit()
方法會將所有待處理的動作傳送至關聯的 stream
,並清除待處理動作的內部清單。
rl.cursorTo(x[, y])
#
rl.cursorTo()
方法會將將游標移至關聯 stream
中指定位置的動作加入到待處理動作的內部清單中。呼叫 rl.commit()
以查看此方法的效果,除非建構函式傳遞了 autoCommit: true
。
rl.moveCursor(dx, dy)
#
rl.moveCursor()
方法會將將游標相對於其在關聯 stream
中的目前位置移動的動作加入到待處理動作的內部清單中。呼叫 rl.commit()
以查看此方法的效果,除非建構函式傳遞了 autoCommit: true
。
rl.rollback()
#
- 傳回:這個
rl.rollback
方法會清除待處理動作的內部清單,而不會將其傳送至關聯的 stream
。
readlinePromises.createInterface(options)
#
options
<Object>input
<stream.Readable> 要監聽的 Readable 串流。此選項為必要。output
<stream.Writable> 要將 readline 資料寫入的 Writable 串流。completer
<Function> 用於 Tab 自動完成的選用函式。terminal
<boolean> 如果input
和output
串流應視為 TTY,並寫入 ANSI/VT100 逸出碼,則為true
。預設:建立執行個體時檢查output
串流上的isTTY
。history
<string[]> 歷程記錄行之初始清單。此選項僅在使用者或內部output
檢查將terminal
設為true
時才有意義,否則歷程記錄快取機制根本不會初始化。預設:[]
。historySize
<number> 保留的最大歷程記錄行數。若要停用歷程記錄,請將此值設為0
。此選項僅在使用者或內部output
檢查將terminal
設為true
時才有意義,否則歷程記錄快取機制根本不會初始化。預設:30
。removeHistoryDuplicates
<boolean> 如果為true
,當新增至歷程記錄清單的新輸入行與舊行重複時,會從清單中移除舊行。預設:false
。prompt
<字串> 要使用的提示字串。預設:'> '
。crlfDelay
<數字> 如果\r
和\n
之間的延遲超過crlfDelay
毫秒,\r
和\n
都將被視為獨立的行尾輸入。crlfDelay
將被強制轉換為不小於100
的數字。它可以設定為Infinity
,這種情況下,\r
後接\n
將始終被視為單一換行符(對於使用\r\n
行分隔符讀取檔案可能是合理的)。預設:100
。escapeCodeTimeout
<數字>readlinePromises
將等待字元(以毫秒為單位讀取有歧義的按鍵順序時,可以使用到目前為止讀取的輸入形成完整按鍵順序,也可以採用額外的輸入來完成更長的按鍵順序)的持續時間。預設:500
。tabSize
<整數> 標籤等於的空格數(最小 1)。預設:8
。
- 傳回:<readlinePromises.Interface>
readlinePromises.createInterface()
方法會建立新的 readlinePromises.Interface
執行個體。
const readlinePromises = require('node:readline/promises');
const rl = readlinePromises.createInterface({
input: process.stdin,
output: process.stdout,
});
建立 readlinePromises.Interface
執行個體後,最常見的狀況是監聽 'line'
事件
rl.on('line', (line) => {
console.log(`Received: ${line}`);
});
如果這個執行個體的 terminal
為 true
,則 output
串流將獲得最佳相容性,如果它定義 output.columns
屬性,並且在欄位變更時或變更後發出 output
上的 'resize'
事件(process.stdout
在它是 TTY 時會自動執行此動作)。
使用 completer
函數#
completer
函數將使用者輸入的目前列作為引數,並傳回包含 2 個條目的 Array
- 包含與完成相符條目的
Array
。 - 用於配對的子字串。
例如:[[substr1, substr2, ...], originalsubstring]
。
function completer(line) {
const completions = '.help .error .exit .quit .q'.split(' ');
const hits = completions.filter((c) => c.startsWith(line));
// Show all completions if none found
return [hits.length ? hits : completions, line];
}
completer
函數也可以傳回 <Promise>,或為非同步
async function completer(linePartial) {
await someAsyncWork();
return [['123'], linePartial];
}
回呼 API#
類別:readline.Interface
#
readline.Interface
類別的執行個體是使用 readline.createInterface()
方法建構的。每個執行個體都與單一 input
Readable 串流和單一 output
Writable 串流關聯。output
串流用於列印使用者輸入提示,而輸入提示會出現在 input
串流上並從中讀取。
rl.question(query[, options], callback)
#
query
<string> 要寫入output
的陳述或查詢,附加在提示之前。options
<Object>signal
<AbortSignal> 選擇性地允許使用AbortController
取消question()
。
callback
<函式> 呼叫函式,會在回應query
時呼叫,並帶有使用者的輸入。
rl.question()
方法透過將 query
寫入 output
來顯示,等待使用者在 input
上提供輸入,然後呼叫 callback
函式,並將提供的輸入作為第一個引數傳遞。
呼叫時,如果 input
串流已暫停,rl.question()
會繼續串流。
如果 readline.Interface
是使用 output
設定為 null
或 undefined
建立的,則不會寫入 query
。
傳遞給 rl.question()
的 callback
函式不遵循接受 Error
物件或 null
作為第一個引數的典型模式。callback
會呼叫,並將提供的答案作為唯一的引數。
如果在 rl.close()
之後呼叫 rl.question()
,將會擲回錯誤。
範例用法
rl.question('What is your favorite food? ', (answer) => {
console.log(`Oh, so your favorite food is ${answer}`);
});
使用 AbortController
取消問題。
const ac = new AbortController();
const signal = ac.signal;
rl.question('What is your favorite food? ', { signal }, (answer) => {
console.log(`Oh, so your favorite food is ${answer}`);
});
signal.addEventListener('abort', () => {
console.log('The food question timed out');
}, { once: true });
setTimeout(() => ac.abort(), 10000);
readline.clearLine(stream, dir[, callback])
#
stream
<stream.Writable>dir
<數字>-1
:從游標向左1
:從游標向右0
:整行
callback
<函式> 在作業完成後呼叫。- 傳回:<布林> 如果
stream
希望呼叫程式碼等待'drain'
事件發出後再繼續寫入其他資料,則為false
;否則為true
。
readline.clearLine()
方法會清除指定 TTY 串流中由 dir
識別的特定方向的目前行。
readline.clearScreenDown(stream[, callback])
#
stream
<stream.Writable>callback
<函式> 在作業完成後呼叫。- 傳回:<布林> 如果
stream
希望呼叫程式碼等待'drain'
事件發出後再繼續寫入其他資料,則為false
;否則為true
。
readline.clearScreenDown()
方法會清除給定的 TTY 串流中,從游標目前位置向下開始的部分。
readline.createInterface(options)
#
options
<Object>input
<stream.Readable> 要監聽的 Readable 串流。此選項為必要。output
<stream.Writable> 要將 readline 資料寫入的 Writable 串流。completer
<Function> 用於 Tab 自動完成的選用函式。terminal
<boolean> 如果input
和output
串流應視為 TTY,並寫入 ANSI/VT100 逸出碼,則為true
。預設:建立執行個體時檢查output
串流上的isTTY
。history
<string[]> 歷程記錄行之初始清單。此選項僅在使用者或內部output
檢查將terminal
設為true
時才有意義,否則歷程記錄快取機制根本不會初始化。預設:[]
。historySize
<number> 保留的最大歷程記錄行數。若要停用歷程記錄,請將此值設為0
。此選項僅在使用者或內部output
檢查將terminal
設為true
時才有意義,否則歷程記錄快取機制根本不會初始化。預設:30
。removeHistoryDuplicates
<boolean> 如果為true
,當新增至歷程記錄清單的新輸入行與舊行重複時,會從清單中移除舊行。預設:false
。prompt
<字串> 要使用的提示字串。預設:'> '
。crlfDelay
<數字> 如果\r
和\n
之間的延遲超過crlfDelay
毫秒,\r
和\n
都將被視為獨立的行尾輸入。crlfDelay
將被強制轉換為不小於100
的數字。它可以設定為Infinity
,這種情況下,\r
後接\n
將始終被視為單一換行符(對於使用\r\n
行分隔符讀取檔案可能是合理的)。預設:100
。escapeCodeTimeout
<number>readline
會等待字元的時間(以毫秒為單位,在讀取模稜兩可的按鍵順序時,該順序既可以使用到目前為止讀取的輸入,形成完整的按鍵順序,也可以接受其他輸入,完成更長的按鍵順序)。預設值:500
。tabSize
<整數> 標籤等於的空格數(最小 1)。預設:8
。signal
<AbortSignal> 允許使用 AbortSignal 關閉介面。中斷訊號會在內部對介面上呼叫close
。
- 傳回:<readline.Interface>
readline.createInterface()
方法會建立新的 readline.Interface
執行個體。
const readline = require('node:readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
建立 readline.Interface
執行個體後,最常見的狀況是聆聽 'line'
事件
rl.on('line', (line) => {
console.log(`Received: ${line}`);
});
如果這個執行個體的 terminal
為 true
,則 output
串流將獲得最佳相容性,如果它定義 output.columns
屬性,並且在欄位變更時或變更後發出 output
上的 'resize'
事件(process.stdout
在它是 TTY 時會自動執行此動作)。
使用 stdin
作為輸入建立 readline.Interface
時,程式不會終止,直到收到 EOF 字元。若要退出而不等候使用者輸入,請呼叫 process.stdin.unref()
。
completer
函數的使用#
completer
函數將使用者輸入的目前列作為引數,並傳回包含 2 個條目的 Array
- 包含與完成相符條目的
Array
。 - 用於配對的子字串。
例如:[[substr1, substr2, ...], originalsubstring]
。
function completer(line) {
const completions = '.help .error .exit .quit .q'.split(' ');
const hits = completions.filter((c) => c.startsWith(line));
// Show all completions if none found
return [hits.length ? hits : completions, line];
}
如果 completer
函數接受兩個參數,則可以非同步呼叫
function completer(linePartial, callback) {
callback(null, [['123'], linePartial]);
}
readline.cursorTo(stream, x[, y][, callback])
#
stream
<stream.Writable>x
<number>y
<number>callback
<函式> 在作業完成後呼叫。- 傳回:<布林> 如果
stream
希望呼叫程式碼等待'drain'
事件發出後再繼續寫入其他資料,則為false
;否則為true
。
readline.cursorTo()
方法將游標移至給定 TTY stream
中指定的位置。
readline.moveCursor(stream, dx, dy[, callback])
#
stream
<stream.Writable>dx
<number>dy
<number>callback
<函式> 在作業完成後呼叫。- 傳回:<布林> 如果
stream
希望呼叫程式碼等待'drain'
事件發出後再繼續寫入其他資料,則為false
;否則為true
。
readline.moveCursor()
方法將游標相對於其在給定 TTY stream
中的目前位置進行移動。
readline.emitKeypressEvents(stream[, interface])
#
stream
<stream.Readable>interface
<readline.InterfaceConstructor>
readline.emitKeypressEvents()
方法會讓給定的 Readable stream 開始發出與接收輸入相應的 'keypress'
事件。
interface
選擇性地指定一個 readline.Interface
實例,當偵測到貼上輸入時,此實例會停用自動完成。
如果 stream
是 TTY,則它必須處於原始模式。
如果 input
是終端機,則任何 readline 實例都會在 input
上自動呼叫此方法。關閉 readline
實例不會阻止 input
發出 'keypress'
事件。
readline.emitKeypressEvents(process.stdin);
if (process.stdin.isTTY)
process.stdin.setRawMode(true);
範例:微型 CLI#
以下範例說明如何使用 readline.Interface
類別來實作小型命令列介面
const readline = require('node:readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: 'OHAI> ',
});
rl.prompt();
rl.on('line', (line) => {
switch (line.trim()) {
case 'hello':
console.log('world!');
break;
default:
console.log(`Say what? I might have heard '${line.trim()}'`);
break;
}
rl.prompt();
}).on('close', () => {
console.log('Have a great day!');
process.exit(0);
});
範例:逐行讀取檔案串流#
readline
的常見使用案例是逐行使用輸入檔案。最簡單的方法是利用 fs.ReadStream
API 以及 for await...of
迴圈
const fs = require('node:fs');
const readline = require('node:readline');
async function processLineByLine() {
const fileStream = fs.createReadStream('input.txt');
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity,
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
}
}
processLineByLine();
或者,可以使用 'line'
事件
const fs = require('node:fs');
const readline = require('node:readline');
const rl = readline.createInterface({
input: fs.createReadStream('sample.txt'),
crlfDelay: Infinity,
});
rl.on('line', (line) => {
console.log(`Line from file: ${line}`);
});
目前,for await...of
迴圈可能會慢一些。如果 async
/ await
流程和速度都很重要,則可以套用混合方法
const { once } = require('node:events');
const { createReadStream } = require('node:fs');
const { createInterface } = require('node:readline');
(async function processLineByLine() {
try {
const rl = createInterface({
input: createReadStream('big-file.txt'),
crlfDelay: Infinity,
});
rl.on('line', (line) => {
// Process the line.
});
await once(rl, 'close');
console.log('File processed.');
} catch (err) {
console.error(err);
}
})();
TTY 鍵盤繫結#
鍵盤繫結 | 說明 | 注意事項 |
---|---|---|
Ctrl+Shift+Backspace | 刪除左邊一行 | 不適用於 Linux、Mac 和 Windows |
Ctrl+Shift+Delete | 刪除右邊一行 | 不適用於 Mac |
Ctrl+C | 發出 SIGINT 或關閉 readline 實例 |
|
Ctrl+H | 刪除左邊 | |
Ctrl+D | 刪除右邊或在目前行為空值/EOF 時關閉 readline 實例 | 不適用於 Windows |
Ctrl+U | 從目前位置刪除到行首 | |
Ctrl+K | 從目前位置刪除到行尾 | |
Ctrl+Y | Yank(還原)先前刪除的文字 | 僅適用於使用 Ctrl+U 或 Ctrl+K 刪除的文字 |
Meta+Y | 在先前刪除的文字之間循環 | 僅在最後按下的按鍵為 Ctrl+Y 或 Meta+Y 時可用 |
Ctrl+A | 移至行首 | |
Ctrl+E | 移至行尾 | |
Ctrl+B | 向後一個字元 | |
Ctrl+F | 向前一個字元 | |
Ctrl+L | 清除畫面 | |
Ctrl+N | 下一項歷史記錄 | |
Ctrl+P | 上一項歷史記錄 | |
Ctrl+- | 復原上一次變更 | 任何發出鍵碼 0x1F 的按鍵都會執行此動作。在許多終端機中,例如 xterm ,此鍵碼會繫結至 Ctrl+-。 |
Ctrl+6 | 重做上一次變更 | 許多終端機沒有預設的重做按鍵。我們選擇鍵碼 0x1E 來執行重做。在 xterm 中,預設會將其繫結至 Ctrl+6。 |
Ctrl+Z | 將正在執行的程序移至背景。輸入 fg 並按下 Enter 以返回。 |
不適用於 Windows |
Ctrl+W 或 Ctrl +Backspace | 向後刪除至字詞邊界 | Ctrl+Backspace 在 Linux、Mac 和 Windows 上無法使用 |
Ctrl+Delete | 向前刪除至字詞邊界 | 不適用於 Mac |
Ctrl+向左箭頭 或 Meta+B | 字詞向左 | Ctrl+向左箭頭 在 Mac 上無法使用 |
Ctrl+向右箭頭 或 Meta+F | 字詞向右 | Ctrl+向右箭頭 在 Mac 上無法使用 |
Meta+D 或 Meta +Delete | 刪除字詞向右 | Meta+Delete 在 Windows 上無法使用 |
Meta+Backspace | 刪除字詞向左 | 不適用於 Mac |