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

6

我读到的关于Node.js事件发射器的文章都是关于如何创建它们。然而,我还没有看到一个具体的例子,说明为什么要使用它们而不仅仅使用简单的函数。例如,这是我在一本书中阅读的如何通过构造函数在自定义对象上使用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);

然而,以下代码也可以得到相同的结果:
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);

我想知道在 Node.js 中使用事件发射器是一种设计选择还是必需品。我知道理解它们是必要的,因为许多模块采用了这种模式,但我很好奇是否选择它类似于使用工厂函数而不是构造函数等。换句话说,我能否通过 EventEmitters 做到一些无法使用函数实现的事情?


1
像往常一样:抽象化。虽然你可以不用它,但你的代码会变得混乱不堪。 - Bergi
1个回答

11

EventEmitter是用于实现发布-订阅模式的。其思想是,发布者(在此示例中为MusicPlayer)不知道或不关心谁订阅了他的消息。他只需要发出正确的事件,任何监听它们的人都将收到有关事件的适当通知。

实现发布-订阅模式可以减轻应用程序各个模块之间的耦合。


谢谢,我明白了。所以这就像安卓的事件总线概念。 - Woppi
但是普通函数也不关心它发送响应给谁,对吧? - Matt123
2
没错。不同之处在于,对于常规函数,调用者是发起者。可以说调用者从函数中“拉”出消息(返回值)。在发布-订阅模式的情况下,想法是只要有新消息准备好了,就会通知调用者,而不一定是在订阅时(发射器向订阅者“推送”消息)。此外,在常规函数调用的情况下,每次调用只返回一个值。事件发射器可以发出给定消息0、1或多个(甚至无限次)。 - Bartosz Gościński

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接