seriously like the best async child process library
(I'm joking, you may want to use execa
which has a lot more features. The minor advantages of this package are,
it's a dual CJS/ESM package, and it provides wrappers for all the async child_process
functions.)
Based upon child-process-async
,
but more thorough, because that package doesn't seem very actively maintained.
promisify-child-process
provides a drop-in replacement for the
original child_process
functions, not just duplicate methods that
return a Promise
. So when you call exec(...)
we still return a
ChildProcess
instance, just with .then()
, .catch()
, and .finally()
added to
make it promise-friendly.
npm install --save promisify-child-process
If you are using a old version of Node without built-in Promise
s or
Object.create
, you will need to use polyfills (e.g. @babel/polyfill
).
// OLD:
const { exec, spawn, fork, execFile } = require('child_process')
// NEW:
const { exec, spawn, fork, execFile } = require('promisify-child-process')
You must now pass maxBuffer
or encoding
to spawn
/fork
if you want to
capture stdout
or stderr
.
The child process promise will only resolve if the process exits with a code of 0.
If it exits with any other code, is killed by a signal, or emits an 'error'
event,
the promise will reject.
exec
and execFile
capture stdout
and stderr
by default. But spawn
and
fork
don't capture stdout
and stderr
unless you pass an encoding
or
maxBuffer
option:
const { spawn } = require('promisify-child-process');
async function() {
// captures output
const { stdout, stderr } = await spawn('ls', [ '-al' ], {encoding: 'utf8'});
const { stdout, stderr } = await spawn('ls', [ '-al' ], {maxBuffer: 200 * 1024});
// BUG, DOESN'T CAPTURE OUTPUT:
const { stdout, stderr } = await spawn('ls', [ '-al' ]);
}
If the child process promise rejects, the error may have the following additional properties:
code
- the process' exit code (if it exited)signal
- the signal the process was killed with (if it was killed)stdout
- the capturedstdout
(if output capturing was enabled)stderr
- the capturedstderr
(if output capturing was enabled)
If for any reason you need to wrap a ChildProcess
you didn't create,
you can use the exported promisifyChildProcess
function:
const { promisifyChildProcess } = require('promisify-child-process');
async function() {
const { stdout, stderr } = await promisifyChildProcess(
some3rdPartyFunctionThatReturnsChildProcess(),
{ encoding: 'utf8' }
)
}
async function() {
const { stdout, stderr } = await exec('ls -al');
// OR:
const child = exec('ls -al', {});
// do whatever you want with `child` here - it's a ChildProcess instance just
// with promise-friendly `.then()` & `.catch()` functions added to it!
child.stdin.write(...);
child.stdout.pipe(...);
child.stderr.on('data', (data) => ...);
const { stdout, stderr } = await child;
}
async function() {
const { stdout, stderr, code } = await spawn('ls', [ '-al' ], {encoding: 'utf8'});
// OR:
const child = spawn('ls', [ '-al' ], {});
// do whatever you want with `child` here - it's a ChildProcess instance just
// with promise-friendly `.then()` & `.catch()` functions added to it!
child.stdin.write(...);
child.stdout.pipe(...);
child.stderr.on('data', (data) => ...);
const { stdout, stderr, code } = await child;
}