Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
child_process: support promisified exec(File)
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
commit fe5ca3ff27d3d94386edab0f9328df534da599aa
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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that it is quite tedious to do so, but examples would be good for these

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I might be pedantic here, but we are ignoring the returned promise.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thefourtheye Yes … got a better suggestion? Just leave this line out? ;)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmmm, to think of it, that sounds better to me.

```

### 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'));
}));
}