为什么使用Node.js EventEmitter而不仅仅是普通函数?

Wil*_*iam 4 design-patterns publish-subscribe node.js

我读到的关于节点EventEmitters的每篇文章都讨论了如何创建它们.但是,我还没有看到为什么要使用它们而不仅仅是一个简单的函数的具体示例.例如,这是一本书中的一个例子,我正在阅读如何通过其构造函数在自定义对象上使用EventEmitter类.


    var util = require('util');
    var events = require('events');
    var AudioDevice = {
        play: function(track) {
            // Stub: Trigger playback through iTunes, mpg123, etc.
            console.log("playing song: " + track);
        },
        stop: function() {
            console.log("song stopped");
        }
    };

    function MusicPlayer() {
        this.playing = false;
        events.EventEmitter.call(this);
    }

    util.inherits(MusicPlayer, events.EventEmitter);

    var musicPlayer = new MusicPlayer();

    musicPlayer.on('play', function(track) {
        this.playing = true;
        AudioDevice.play(track);
    });

    musicPlayer.on('stop', function() {
        this.playing = false;
        AudioDevice.stop();
    });

    musicPlayer.emit('play', 'The Roots - The Fire');

    setTimeout(function() {
        musicPlayer.emit('stop');
    }, 1000);
Run Code Online (Sandbox Code Playgroud)

但是,以下给出了相同的结果:


var AudioDevice = {
    play: function(track) {
        // Stub: Trigger playback through iTunes, mpg123, etc.
        console.log("playing song: " + track);
    },
    stop: function() {
        console.log("song stopped");
    }
};

function createMusicPlayer() {
    var musicPlayer = {};
    musicPlayer.playing = false;
    musicPlayer.play = function(track) {
        musicPlayer.playing = true;
        AudioDevice.play(track);
    },
    musicPlayer.stop = function(track) {
        musicPlayer.playing = false;
        AudioDevice.stop();
    }

    return musicPlayer
}

var musicPlayer = createMusicPlayer();

musicPlayer.play('The Roots - The Fire');

setTimeout(function() {
    musicPlayer.stop();
}, 1000);
Run Code Online (Sandbox Code Playgroud)

我想知道在使用节点时事件发射器是设计选择还是必需品.我知道有必要理解它们,因为很多模块都使用这种模式,但我很好奇这个选择是否类似于使用工厂而不是构造函数等.换句话说,我可以用EventEmitters做任何我无法用函数做的事情?

Bar*_*ski 9

EventEmitters用于实现发布 - 订阅模式.这里的想法是发布者 - 在你的例子中MusicPlayer- 不知道或关心谁订阅他的消息.他的工作只是发出适当的事件,无论谁听到他们都会得到有关事件的适当通知.

实现发布 - 订阅模式可以减轻应用程序区域之间的耦合.

  • 这是正确的。不同之处在于,对于常规函数,调用者是发起者。可以说调用者从函数中“拉”出消息(返回值)。在 pubsub 模式的情况下,其想法是每当新消息准备好时,调用者都会收到通知,而不一定是在订阅时(发送者将消息“推送”给订阅者)。此外,在常规函数调用的情况下,每次调用仅返回一个值。事件发射器可以发射给定消息 0 次、1 次或多次(甚至无限次) (2认同)