使用事件发射器实现的简单发布/订阅系统

3

这段内容出自书籍《Node.JS实战》,第3章,例子11,第52页。

var events = require('events');
var net = require('net');


var channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};

//Add a listener for the join event that stores a user’s client object, 
//allowing the application to send data back to the user.

channel.on('join', function(id, client) {
    console.log('join fired');
    channel.clients[id] = client;
    this.subscriptions[id] = function(senderId, message) {
        console.log('broadcast fired');
            //ignore data if it’s been directly broadcast by the user.
            if (id != senderId) {
                this.clients[id].write(message);
            }
        }
        //Add a listener, specific to the current user, for the broadcast event.
    this.on('broadcast', this.subscriptions[id]);

});

var server = net.createServer(function(client) {
    var id = client.remoteAddress + ':' + client.remotePort;
    client.on('connect', function() {
        console.log('connect fired');
        //Emit a join event when a user connects to the server, specifying the user ID and client object.
        channel.emit('join', id, client);
    });
    client.on('data', function(data) {
        console.log('data fired');
        data = data.toString();
        //Emit a channel broadcast event, specifying the user ID and message, when any user sends data.
        channel.emit('broadcast', id, data);
    });
});
server.listen(8888);

这个聊天应用可以做到以下几点:

"如果你打开几个命令行,你会发现在一个命令行中输入的任何内容都会被其他命令行回显。"

我添加了console.log()事件来尝试调试发生了什么。但是我唯一得到的日志是发送消息时的"data fired"。虽然我能够启动服务器,并通过telnet连接到它,但是输入的任何消息都不会回显到任何客户端(包括发送消息的客户端)。

有人能解释一下:

  1. 为什么这个不起作用
  2. 是否高效或推荐的代码结构
  3. 如何改进/纠正它

你能否为我提供有关Join和Broadcast Listener的文档? - loveNoHate
这是完整描述的函数。连接客户端对象时,将发出join事件;当数据从客户端传递时,将发出broadcast事件。这两个函数位于net.createServer()内部底部。 - Aweary
这是我所能获得的最接近的内容:http://nodejs.org/api/net.html#net_event_connect - loveNoHate
啊哈,抱歉我明白了,这些是自定义事件,妈妈。 - loveNoHate
1个回答

3

对于传递给createServer()回调函数的传入套接字,不存在connect事件。当调用回调函数时,套接字已经连接。所以书中存在错误。

您还应该注意this的使用。

在我看来,这是一个更好的例子:

var events = require('events');
var net = require('net');

var channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};

channel.on('join', function(id, client) {
  channel.clients[id] = client;
  channel.subscriptions[id] = function(senderId, message) {
    if (id !== senderId)
      channel.clients[id].write(message);
  }
  channel.on('broadcast', channel.subscriptions[id]);
}).on('leave', function(id, client) {
  // cleanup on client disconnect
  console.log('user ' + id + ' has left');
  delete channel.clients[id];
  channel.removeListener('broadcast', channel.subscriptions[id]);
  delete channel.subscriptions[id];
});

var server = net.createServer(function(client) {
  var id = client.remoteAddress + ':' + client.remotePort;

  console.log('user ' + id + ' has joined');

  channel.emit('join', id, client);

  client.on('data', function(data) {
    channel.emit('broadcast', id, data.toString());
  }).on('close', function() {
    channel.emit('leave', id, client);
  });
});
server.listen(8888);

进一步的改进是仅有一个事件处理程序,循环遍历所有连接的套接字,而不是为每个单独的套接字添加一个新的事件处理程序。

谢谢,这就是我需要的。 - Aweary
你还应该注意>>这个<<用法。你可以通过一个例子来说明这一点,或者提供一个解释的链接。谢谢! - Gerd

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