ビルトインの readline モジュールはユーザーからの入力受付用かと思っていましたが ファイルの読み取りにも使えるみたいです

const fs = require("fs")
const readline = require("readline")

const fn = async () => {
fs.writeFileSync("test.txt", "foo\nbar\nbaz")

const rl = readline.createInterface({ input: fs.createReadStream("test.txt") })
for await (const line of rl) {
console.log({ line })
}
}

fn()
{ line: 'foo' }
{ line: 'bar' }
{ line: 'baz' }

readline で作成した Interface は async iterator を持ってるので for-await-of で使えます

const readline = require("readline")

const rl = readline.createInterface({
input: { on(){}, resume() {} }
})

console.log(rl[Symbol.iterator])
// undefined
console.log(rl[Symbol.asyncIterator])
// [Function (anonymous)]

Node.js 17 から readline に Promise API が追加されています
これは question みたいな関数がコールバックか Promise かの違いで 行ごとに読み取るだけなら 16 まででも使えます
18 以降でも変わりないです

注意しないといけないのがこういうケースです

const fs = require("fs")
const readline = require("readline")

const fn = async () => {
fs.writeFileSync("test.txt", "foo\nbar\nbaz")

const rl = readline.createInterface({ input: fs.createReadStream("test.txt") })

await new Promise(r => setTimeout(r, 100))

console.log(1)
for await (const line of rl) {
console.log({ line })
}
console.log(2)
}

fn()

readline の Interface を作ってから for-await-of で読むまでに非同期処理を挟む場合です
これを実行すると 1 だけが出力されます
for-await-of では待機したままデータなしになって 解決しない Promise という扱いで それ以降実行できるものがなくプロセスが終了します
その結果 2 を出力する console.log にたどり着かないので出力は 1 だけです

内部で stream の resume が呼び出されるので自動で読み進めてしまうみたいです
非同期処理を挟まず for-await-of を実行すると asyncIterator の作成処理で stream のイベントが起きる前にリスナを設定できます
その結果 正常に line イベントなどを受け取れて期待どおりに動作します
しかし 非同期処理を挟むと先にイベントが起きてしまって stream が close されたあとにリスナをつけることになるのでなんのイベントも起きず解決されない Promise になるということみたいです