为了说清楚这两种方式的不同,现在来做一个任务:
启动3个子进程,调用系统
echo
输出二进制数字,并且把输出的数字保存在3个文件中。过程类似这样:$ echo 00 > echo0.log $ echo 00 01 > echo1.log $ echo 00 01 10 > echo2.log
这3个子进程是并行进行的,而不是串行,也就是每一个子进程不会存在等待。 当3个子进程全部运行完成时,程序控制退出主进程。
共享计数器
要同时启动3个子进程,并能在进程结束时,主进程能够获取控制权,那么最简单有效的方式,莫过于使用计数器。
我们使用count
这个变量来表示当前的子进程数量。每个子进程完成时,都会修改这个共享的全局变量。
面向对象
建立一个Writer
对象,来作为主进程的表示,如下:
-
继承events.EventEmitter,成为一个事件对象,提供
finish
事件 -
_count
作为内部计数器 -
write()
方法会启动一个子进程,进行文件echo
输出,并操作计数器- 启动一个子进程时,计数器加1
- 子进程完成时,计数器减1
- 计数器归0时,触发
finish
事件 finish
触发时,退出主进程
var cp = require('child_process'),
fs = require('fs'),
path = require('path'),
events = require('events'),
filepath0 = path.join(__dirname, 'echo0.log'),
filepath1 = path.join(__dirname, 'echo1.log'),
filepath2 = path.join(__dirname, 'echo2.log');
function Writer() {
if (!(this instanceof Writer)) {
return new Writer();
}
events.EventEmitter.call(this);
this._count = 0;
}
Writer.prototype = Object.create(events.EventEmitter.prototype);
Writer.prototype._written = function () {
if (--this._count === 0) {
this.emit('finish');
}
};
Writer.prototype.write = function (cmd, args, filepath) {
var child = cp.spawn(cmd, args),
data = '',
writer = this;
++writer._count;
console.log('The cmd is: %s.', cmd + ' ' + args.join(' '));
child.stdout
.setEncoding('utf8')
.on('data', function (d) {
data += d;
})
.on('end', function () {
console.log('Writing to file ...');
fs.writeFileSync(filepath, data, 'utf8');
writer._written();
});
return writer;
};
Writer()
.on('finish', function () {
console.log('Complete echos.');
process.exit(0);
})
.write('echo', ['00'], filepath0)
.write('echo', ['00', '01'], filepath1)
.write('echo', ['00', '01', '10'], filepath2);
面向函数
-
count
作为共享计数器 -
建立一个
write()
函数,来启动一个子进程- 启动一个子进程时,计数器加1
- 子进程完成时,计数器减1,触发主进程
written
事件 - 计数器归0时,退出主进程
var cp = require('child_process'),
fs = require('fs'),
path = require('path'),
filepath0 = path.join(__dirname, 'echo0.log'),
filepath1 = path.join(__dirname, 'echo1.log'),
filepath2 = path.join(__dirname, 'echo2.log'),
count = 0;
function write(cmd, args, filepath) {
var child = cp.spawn(cmd, args),
data = '';
count = count + 1;
console.log('The cmd is: %s.', cmd + ' ' + args.join(' '));
child.stdout
.setEncoding('utf8')
.on('data', function (d) {
data += d;
})
.on('end', function () {
console.log('Writing to file ...');
fs.writeFileSync(filepath, data, 'utf8');
process.emit('written');
});
}
process.on('written', function () {
if (--count === 0) {
console.log('Complete echos.');
process.exit(0);
}
});
write('echo', ['00'], filepath0);
write('echo', ['00', '01'], filepath1);
write('echo', ['00', '01', '10'], filepath2);