Skip to content

[BUG] fails to read more than one line under certain conditions #36

Description

@obfusk

Using read to prompt multiple times fails after the first line when:

  • input is non-interactive (e.g. file/pipe); and
  • use is asynchronous wrt "nesting" (replacing setTimeout(f) with f() seems to "fix" the issue)

Test case x.js

const read = require("read")
const f = () => read({ prompt: ">" }, (e, line) => {
  if (e) { throw e }
  console.log("got:", line)
  setTimeout(f)
})
f()

Interactive user input in terminal: works

$ node x.js 
> foo
got: foo
> bar
got: bar
> baz
got: baz
> ^D

Non-interactive input from file/pipe: only reads first line

$ node x.js <<< $'foo\nbar\nbaz' 
> foo
got: foo
> $ 

Solution?

I've replaced my use of read with the following code, which has fewer features but works:

const _readline = require("readline")
const _rl_buf   = []

const read_line = (prompt = null) =>
  new Promise((resolve, reject) => {
    const p = prompt || "", i = process.stdin, o = process.stdout
    if (_rl_buf.length) {
      if (p) { o.write(p) }
      resolve(_rl_buf.shift())
      return
    }
    const rl = _readline.createInterface({
      input: i, output: o, prompt: p, terminal: false
    })
    let done = false
    const f = (g, h = null) => {
      if (!done) { done = true; rl.close(); g() }
      else if (h) { h() }
    }
    rl.on("line"  , line => f(() => resolve(line),
                              () => _rl_buf.push(line)))
    rl.on("close" , ()   => f(() => resolve(null)))
    rl.on("error" , e    => f(() => reject(e)))
    rl.prompt()
  })

const f = () => read_line("> ").then(line => {
  if (line == null) { return }
  console.log("got:", line)
  setTimeout(f)
})
f()
$ node y.js 
> foo
got: foo
> bar
got: bar
> baz
got: baz
> $ node y.js <<< $'foo\nbar\nbaz' 
> got: foo
> got: bar
> got: baz
> $

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions