Skip to content

Commit

Permalink
child_process: support promisified exec(File)
Browse files Browse the repository at this point in the history
Author: Benjamin Gruenbaum <inglor@gmail.com>
Author: Anna Henningsen <anna@addaleax.net>

PR-URL: #12442
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
Reviewed-By: William Kapke <william.kapke@gmail.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Teddy Katz <teddy.katz@gmail.com>
  • Loading branch information
addaleax committed May 9, 2017
1 parent fbcb4f5 commit fe5ca3f
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 1 deletion.
31 changes: 31 additions & 0 deletions doc/api/child_process.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,23 @@ child runs longer than `timeout` milliseconds.
*Note: Unlike the exec(3) POSIX system call, `child_process.exec()` does not
replace the existing process and uses a shell to execute the command.*

If this method is invoked as its [`util.promisify()`][]ed version, it returns
a Promise for an object with `stdout` and `stderr` properties.

For example:

```js
const util = require('util');
const exec = util.promisify(require('child_process').exec);

async function lsExample() {
const {stdout, stderr} = await exec('ls');
console.log('stdout:', stdout);
console.log('stderr:', stderr);
}
lsExample();
```

### child_process.execFile(file[, args][, options][, callback])
<!-- YAML
added: v0.1.91
Expand Down Expand Up @@ -263,6 +280,19 @@ can be used to specify the character encoding used to decode the stdout and
stderr output. If `encoding` is `'buffer'`, or an unrecognized character
encoding, `Buffer` objects will be passed to the callback instead.

If this method is invoked as its [`util.promisify()`][]ed version, it returns
a Promise for an object with `stdout` and `stderr` properties.

```js
const util = require('util');
const execFile = util.promisify(require('child_process').execFile);
async function getVersion() {
const {stdout} = await execFile('node', ['--version']);
console.log(stdout);
}
getVersion();
```

### child_process.fork(modulePath[, args][, options])
<!-- YAML
added: v0.5.0
Expand Down Expand Up @@ -1269,4 +1299,5 @@ to `stdout` although there are only 4 characters.
[`process.on('message')`]: process.html#process_event_message
[`process.send()`]: process.html#process_process_send_message_sendhandle_options_callback
[`stdio`]: #child_process_options_stdio
[`util.promisify()`]: util.html#util_util_promisify_original
[synchronous counterparts]: #child_process_synchronous_process_creation
10 changes: 9 additions & 1 deletion lib/child_process.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
'use strict';

const util = require('util');
const { deprecate, convertToValidSignal } = require('internal/util');
const {
deprecate, convertToValidSignal, customPromisifyArgs
} = require('internal/util');
const debug = util.debuglog('child_process');

const uv = process.binding('uv');
Expand Down Expand Up @@ -138,6 +140,9 @@ exports.exec = function(command /*, options, callback*/) {
opts.callback);
};

Object.defineProperty(exports.exec, customPromisifyArgs,
{ value: ['stdout', 'stderr'], enumerable: false });


exports.execFile = function(file /*, args, options, callback*/) {
var args = [];
Expand Down Expand Up @@ -333,6 +338,9 @@ exports.execFile = function(file /*, args, options, callback*/) {
return child;
};

Object.defineProperty(exports.execFile, customPromisifyArgs,
{ value: ['stdout', 'stderr'], enumerable: false });

const _deprecatedCustomFds = deprecate(
function deprecateCustomFds(options) {
options.stdio = options.customFds.map(function mapCustomFds(fd) {
Expand Down
34 changes: 34 additions & 0 deletions test/parallel/test-child-process-promisified.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const child_process = require('child_process');
const { promisify } = require('util');

common.crashOnUnhandledRejection();

const exec = promisify(child_process.exec);
const execFile = promisify(child_process.execFile);

{
exec(`${process.execPath} -p 42`).then(common.mustCall((obj) => {
assert.deepStrictEqual(obj, { stdout: '42\n', stderr: '' });
}));
}

{
execFile(process.execPath, ['-p', '42']).then(common.mustCall((obj) => {
assert.deepStrictEqual(obj, { stdout: '42\n', stderr: '' });
}));
}

{
exec('doesntexist').catch(common.mustCall((err) => {
assert(err.message.includes('doesntexist'));
}));
}

{
execFile('doesntexist', ['-p', '42']).catch(common.mustCall((err) => {
assert(err.message.includes('doesntexist'));
}));
}

0 comments on commit fe5ca3f

Please sign in to comment.