简体   繁体   中英

How to read data from nodejs spawn as it is received

I have a small problem with a nodejs program. I'm trying to use the child_process module but the following code will only trigger the data event once I remove my card from a nfc card reader.

The problem is that the output I need is available before the card is removed.

For example if I put my card on the reader it will take half a second to print some lines inculding the card UID.

Then if I don't release the card, the program nfc-poll will still be working but won't output anything. As soon as I remove my card from the reader, it will output something and then close the buffer. This is when the event data is emitted.

What I'd like is to be able to read every byte as soon as possible to emit the card id as soon as possible.

function NFCReader() {
  this.reader = new events.EventEmitter()
  this.start_process()
}

NFCReader.prototype = {
  start_process: function () {
    this._process = cp.spawn('nfc-poll', [], {})
    this._process.on('close', this.restart_process.bind(this))
    //this._process.stdout.on('data', this.handle_data.bind(this))
    this._process.stdout.readableFlowing = true
    this._process.stdout.on('data', this.handle_data.bind(this))
    this._process.stderr.on('data', this.handle_error.bind(this))
  },

  handle_data: function (data) {
    var _data = data.toString()
    var uid_lines = _data
      .split('\n')
      .filter(function (line) {return line.search('UID') >= 0})

    if (uid_lines.length != 1) {
      this.reader.emit('error', 'Multiple UID found')
      return
    }

    var card_id = uid_lines[0]
      .trim()
      .split(':')[1].trim()
      .replace(/[ ]+/g, ':')

    this.reader.emit('card', card_id)
  },
}

I tried to use pipe but it doesn't seem to help.

this is a runStream function from my release tools repo :

const stdin = input ? "pipe" : "ignore";
const out = new StringStream();
const child = execspawn(cmd, Object.assign(options, {
    stdio: [stdin, "pipe", 2]
}));

child.on("error", e => out.emit("error", e));

if (input) {
    input.pipe(child.stdin);
}
return child.stdout.pipe(out);

You can reproduce it or if you'd care to wait a couple days I could release it as a separate module. I guess there may already be something like that though...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM