精华 面向对象和面向函数编写异步事件的区别
发布于 8天前 作者 tulayang 178 次浏览 来自 分享

为了说清楚这两种方式的不同,现在来做一个任务:

启动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);

回到顶部