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

时间:2014-10-05 03:26:52

标签: javascript node.js

这来自 Node.JS in Action 一书,第3章,示例11. Page 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()事件来尝试调试正在进行的操作。唯一的日志是get是发送消息时“触发的数据”。我能够启动服务器,并通过telnet连接到它,但输入的任何消息都不会回应任何客户端(包括发送消息的客户端)。

任何人都可以了解一下:

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

1 个答案:

答案 0 :(得分:3)

传入套接字没有connect事件(传递给createServer()回调)。调用回调时,套接字已连接。所以这是本书中的一个错误。

您还应该注意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);

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