Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order of process.stdout.on( 'data', ... ) and process.stderr.on( 'data', ... )

I'm writing an electron app and this app deals with terminal commands executed from within electron.

I've got troubles with the execution of the npm ls command. When running it from the cli the dependency tree is printed to stdout and right at the end some warning might appear coming from stderr.

See screenshot below.

correct output

I digged npm source code a bit and it logs out the results first and afterwards it prints errors. So it's exactly like I see it in my terminal.

However when I do the same with child_process spawn ( or exec it doesn't matter ), the order is different.

puzzled output

It looks like because of the big chunks of stdout data the stderr is printed right in the middle of all the stdout.

The code I wrote below:

// this is mapped to require( 'child_process' ).spawn
this.$set( 'process', this.spawn(
  'npm',
  [ 'ls' ],
  {
    cwd   : options.cwd,

    // following are only my tryouts - nothing helped :(

    // some npm ls command destroy kill the scripts
    // with too big buffers in stdout
    // maxBuffer : 1024 * 5000
    // shell : true
  }
) );

// this.handleData is only printing out for nwo
this.process.stdout.on( 'data', this.handleData );
this.process.stderr.on( 'data', this.handleData );

It seams when large data comes from stdout and tiny data coming from stderr that stderr somehow gets called in the middle.

Is this expected behavior? Can I work around this somehow to retrieve the same behavior as in my terminal?

Thanks. :)

like image 466
stefan judis Avatar asked Oct 27 '25 03:10

stefan judis


1 Answers

process.stdout and process.stderr are not guaranteed to emit data in any particular order relative to each other, so as you've noticed, your callback may be called whenever there's any amount of data in either pipe.

If you want to make sure that the stderr is handled only once all of stdout is finished, you might want to listen to stdout.on('end', cb) and only call stderr.on('data', this.handleData) in that callback cb.


That said, if you just want the results of npm ls, perhaps you might consider trying to use the npm module programmatically? The documentation isn't amazing, but it's a higher-level API.

like image 190
Anko Avatar answered Oct 28 '25 17:10

Anko