Skip to content

Commit fe5ca3f

Browse files
committed
child_process: support promisified exec(File)
Author: Benjamin Gruenbaum <[email protected]> Author: Anna Henningsen <[email protected]> PR-URL: #12442 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Myles Borins <[email protected]> Reviewed-By: Evan Lucas <[email protected]> Reviewed-By: William Kapke <[email protected]> Reviewed-By: Timothy Gu <[email protected]> Reviewed-By: Teddy Katz <[email protected]>
1 parent fbcb4f5 commit fe5ca3f

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

‎doc/api/child_process.md‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,23 @@ child runs longer than `timeout` milliseconds.
214214
*Note: Unlike the exec(3) POSIX system call, `child_process.exec()` does not
215215
replace the existing process and uses a shell to execute the command.*
216216

217+
If this method is invoked as its [`util.promisify()`][]ed version, it returns
218+
a Promise for an object with `stdout` and `stderr` properties.
219+
220+
For example:
221+
222+
```js
223+
constutil=require('util');
224+
constexec=util.promisify(require('child_process').exec);
225+
226+
asyncfunctionlsExample(){
227+
const{stdout, stderr} =awaitexec('ls');
228+
console.log('stdout:', stdout);
229+
console.log('stderr:', stderr);
230+
}
231+
lsExample();
232+
```
233+
217234
### child_process.execFile(file[, args][, options][, callback])
218235
<!-- YAML
219236
added: v0.1.91
@@ -263,6 +280,19 @@ can be used to specify the character encoding used to decode the stdout and
263280
stderr output. If `encoding` is `'buffer'`, or an unrecognized character
264281
encoding, `Buffer` objects will be passed to the callback instead.
265282

283+
If this method is invoked as its [`util.promisify()`][]ed version, it returns
284+
a Promise for an object with `stdout` and `stderr` properties.
285+
286+
```js
287+
constutil=require('util');
288+
constexecFile=util.promisify(require('child_process').execFile);
289+
asyncfunctiongetVersion(){
290+
const{stdout} =awaitexecFile('node', ['--version']);
291+
console.log(stdout);
292+
}
293+
getVersion();
294+
```
295+
266296
### child_process.fork(modulePath[, args][, options])
267297
<!-- YAML
268298
added: v0.5.0
@@ -1269,4 +1299,5 @@ to `stdout` although there are only 4 characters.
12691299
[`process.on('message')`]: process.html#process_event_message
12701300
[`process.send()`]: process.html#process_process_send_message_sendhandle_options_callback
12711301
[`stdio`]: #child_process_options_stdio
1302+
[`util.promisify()`]: util.html#util_util_promisify_original
12721303
[synchronous counterparts]: #child_process_synchronous_process_creation

‎lib/child_process.js‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
'use strict';
2323

2424
constutil=require('util');
25-
const{ deprecate, convertToValidSignal }=require('internal/util');
25+
const{
26+
deprecate, convertToValidSignal, customPromisifyArgs
27+
}=require('internal/util');
2628
constdebug=util.debuglog('child_process');
2729

2830
constuv=process.binding('uv');
@@ -138,6 +140,9 @@ exports.exec = function(command /*, options, callback*/){
138140
opts.callback);
139141
};
140142

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

142147
exports.execFile=function(file/*, args, options, callback*/){
143148
varargs=[];
@@ -333,6 +338,9 @@ exports.execFile = function(file /*, args, options, callback*/){
333338
returnchild;
334339
};
335340

341+
Object.defineProperty(exports.execFile,customPromisifyArgs,
342+
{value: ['stdout','stderr'],enumerable: false});
343+
336344
const_deprecatedCustomFds=deprecate(
337345
functiondeprecateCustomFds(options){
338346
options.stdio=options.customFds.map(functionmapCustomFds(fd){
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict';
2+
constcommon=require('../common');
3+
constassert=require('assert');
4+
constchild_process=require('child_process');
5+
const{ promisify }=require('util');
6+
7+
common.crashOnUnhandledRejection();
8+
9+
constexec=promisify(child_process.exec);
10+
constexecFile=promisify(child_process.execFile);
11+
12+
{
13+
exec(`${process.execPath} -p 42`).then(common.mustCall((obj)=>{
14+
assert.deepStrictEqual(obj,{stdout: '42\n',stderr: ''});
15+
}));
16+
}
17+
18+
{
19+
execFile(process.execPath,['-p','42']).then(common.mustCall((obj)=>{
20+
assert.deepStrictEqual(obj,{stdout: '42\n',stderr: ''});
21+
}));
22+
}
23+
24+
{
25+
exec('doesntexist').catch(common.mustCall((err)=>{
26+
assert(err.message.includes('doesntexist'));
27+
}));
28+
}
29+
30+
{
31+
execFile('doesntexist',['-p','42']).catch(common.mustCall((err)=>{
32+
assert(err.message.includes('doesntexist'));
33+
}));
34+
}

0 commit comments

Comments
(0)