Skip to content

Commit a8033d4

Browse files
committed
test/add addiional way to exexute Node Js forked process with spawn
1 parent 9a48770 commit a8033d4

File tree

4 files changed

+72
-36
lines changed

4 files changed

+72
-36
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ installer('vim')
6262

6363
```js
6464
sudo: boolean, // run as administrator
65+
fork: string, // execute an additional module, of Node Js process `fork` IPC communication channel.
6566
onerror: callable, // callback for `stderr.on('data')` event.
6667
onprogress: callable, // callback for `stdout.on('data')` event.
67-
// onmessage: callable, // callback for send `on('message')` event.
68+
onmessage: callable, // callback for `on('message')` for `fork` event.
6869
```
6970

7071
`Spawning` returns a promise whose result will be any output or any data return in the progress callback.
@@ -77,6 +78,9 @@ installer('vim')
7778
* `output:` *String* - Output from stdout.
7879
* Output can be altered and if returned will replace the otherwise resolved result.
7980

81+
* `fork:` *Object* - An additional [forked](https://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options) Node Js process handler, IPC communication channel.
82+
* Execute additional processing base off of sub child process output, with module a script.
83+
8084
If there's an error running the child process, received data on stderr, or errors in progress callback, `spawning` rejects the returned promise.
8185

8286
### CLI Usage

index.js

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
import which from 'which';
4-
import { spawn } from 'child_process';
4+
import { spawn, fork } from 'child_process';
55
import { dirname, join } from 'path';
66
import { fileURLToPath } from 'url';
77

@@ -176,20 +176,22 @@ function isFunction(value) {
176176
* @param {Object} options - Any child process `spawn` options, defaults: stdio: 'pipe'.
177177
* - Additionally:
178178
*```js
179-
* sudo: boolean, // run as administrator
179+
* sudo: boolean, // run as administrator.
180+
* fork: string, // execute an additional module, a child_process.`fork` IPC communication channel.
180181
* onerror: callable, // callback for `stderr.on('data')` event.
181182
* onprogress: callable, // callback for `stdout.on('data')` event.
182-
// * onmessage: callable, // callback for `on('message')` event.
183+
* onmessage: callable, // callback for `on('message')` for `fork` event.
183184
*```
184185
*/
185186
export const spawning = Sys.spawning = function (command, argument, progressOptions, options) {
186187
return new Promise((resolve, reject) => {
187188
options = options || {
188189
stdio: 'pipe',
189190
sudo: false,
191+
fork: null,
190192
onerror: null,
191193
onprogress: null,
192-
// onmessage: null,
194+
onmessage: null,
193195
};
194196

195197
let progress = progressOptions;
@@ -202,75 +204,80 @@ export const spawning = Sys.spawning = function (command, argument, progressOpti
202204
let error = null;
203205
let output = null;
204206
let sudo = options.sudo || false;
207+
let forking = options.fork || null;
205208
let onerror = options.onerror || null;
206-
//let onmessage = options.onmessage || null;
209+
let onmessage = options.onmessage || null;
210+
211+
if (typeof forking == 'string')
212+
var forked = fork(forking);
207213

208214
delete options.sudo;
215+
delete options.fork;
209216
delete options.onerror;
210217
delete options.onprogress;
211-
//delete options.onmessage;
218+
delete options.onmessage;
212219

213220
if (sudo) {
214221
argument = [command].concat(argument);
215222
command = (process.platform == 'win32') ? join(__dirname, 'bin', 'sudo.bat') : 'sudo';
216-
}
223+
};
224+
225+
const spawned = spawn(command, argument, options);
226+
spawned.on('error', (data) => {
217227

218-
const child = spawn(command, argument, options);
219-
child.on('error', (data) => {
220228
return reject(data);
221229
});
222230

223-
child.on('close', (code) => {
231+
spawned.on('close', (code) => {
224232
if (code === 0) {
225233
return resolve(output);
226234
}
227235

228236
return reject(error, code);
229237
});
230238

231-
child.on('exit', () => {
239+
spawned.on('exit', () => {
240+
if (forked)
241+
setTimeout(() => {
242+
forked.kill();
243+
}, 1000);
244+
232245
return resolve(output);
233246
});
234247

235-
child.stdout.on('data', (data) => {
248+
spawned.stdout.on('data', (data) => {
236249
let input = data.toString();
237-
let onProgress = null
250+
output += input;
238251
try {
239252
if (isFunction(progress)) {
240-
onProgress = progress({ handle: child, output: input });
253+
output = progress({ handle: spawned, output: input, fork: forked }) || output;
241254
}
242255
} catch (e) {
243256
return reject(e.toString());
244257
}
245258

246-
if (onProgress && onProgress != null) {
247-
output = onProgress;
248-
} else if (input != null) {
249-
output += input;
250-
}
251-
252259
if (argument.includes('fake-js')) {
253-
child.kill('SIGKILL');
260+
spawned.kill('SIGKILL');
254261
return resolve('For testing only. ' + output);
255262
}
256263
});
257264

258-
child.stderr.on('data', (data) => {
265+
spawned.stderr.on('data', (data) => {
259266
let err = data.toString();
260-
if (isFunction(onerror))
261-
/* c8 ignore next */
262-
error = onerror(err) || err;
263-
else
264-
error += err;
267+
error += err;
268+
if (isFunction(onerror))/* c8 ignore next */
269+
error = onerror(err) || error;
265270
});
266-
/*
267-
child.on('message', (data) => {
268-
if (isFunction(onmessage))
269-
onmessage(data);
270-
});
271-
*/
271+
272+
if (forked) {
273+
forked.on('message', (data) => {
274+
if (isFunction(onmessage))
275+
onmessage(data);
276+
});
277+
}
278+
272279
if (argument.includes('fake-js') && Object.getOwnPropertyDescriptor(process, 'platform').value == 'darwin') {
273-
child.kill('SIGKILL');
280+
spawned.kill('SIGKILL');
274281
return resolve('For testing only. ' + output);
275282
}
276283
});

test/sub.cjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
process.on('message', (m) => {
2+
console.log('CHILD got message:', m);
3+
});
4+
5+
process.send({ hello: 'world' });

test/test.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,6 @@ describe('Method: `spawning`', function () {
311311
sudo: true,
312312
onerror: (err) => { return 'testing: ' + err; },
313313
onprogress: () => { }
314-
// onmessage: (data) => { console.log('messaging: ' + data); },
315314
})
316315
.then(function () {
317316
done();
@@ -336,6 +335,27 @@ describe('Method: `spawning`', function () {
336335
done();
337336
});
338337
});
338+
339+
it('should receive message from `fork` process', function (done) {
340+
spawning((process.platform == 'win32' ? 'dir' : 'ls'), ['..'], null, {
341+
stdio: 'pipe',
342+
shell: true,
343+
fork: 'test/sub.cjs',
344+
onprogress: (object) => {
345+
expect(object.fork).to.be.instanceOf(Object);
346+
object.fork.send('hello');
347+
return { fork: object.fork, output: 'done' };
348+
},
349+
onmessage: (data) => {
350+
expect(data.hello).to.equal('world');
351+
},
352+
})
353+
.then(function (data) {
354+
expect(data.output).to.equal('done');
355+
expect(data.fork).to.be.instanceOf(Object);
356+
done();
357+
});
358+
});
339359
});
340360

341361
describe('Method: `where`', function () {

0 commit comments

Comments
 (0)