NodeJS入门 0x3 异步编程(2)事件监听

用事件发射器处理重复性事件

    事件发射器示例

    echo 服务器就是一个处理重复性事件的简单例子,当你给它发送数据时,它会把数据发回来。

//echo_server.js
const net = require('net');
const server = net.createServer(socket=>{
	socket.on('data',data=>{//当读取到新数据时处理data事件
		socket.write(data);//把数据写回客户端
	});
});
server.listen(8888);

    启动程序后可以通过telnet进行访问。对于未启用telnet服务可参见win10如何安装telnet服务

    Ctrl+C可结束程序!

     响应只应该发生一次的事件

const net = require('net');
const server = net.createServer(socket => {
	socket.once('data', data => {//data事件只处理一次
		socket.write(data);
	});
});
server.listen(8888);

    创建事件发射器:一个 PUB/SUB 的例子

    事件名称 事件是可以具有任意字符串值的键: data、 join 或某些长的让人发疯的事件名都行。只有一个事件是特殊的,那就是 error。

//telchannel.js
//用 EventEmitter 实现自己的发布/预订逻辑,做一个通信通道。
const events = require('events');
const net = require('net');
const channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};
channel.on('join',function(id,client){
	//添加join事件的监听器,保存用户的client对象
	this.clients[id] = client;
	this.subscriptions[id] = (senderId,message)=>{
		if(id!=senderId){//忽略发送者
			this.clients[id].write(message);
		}
	};
	//添加一个专门针对当前用户的broadcast事件监听器
	this.on('broadcast',this.subscriptions[id]);
});
const server = net.createServer(client=>{
	const id = `${client.remoteAddress}:${client.remotePort}`;
	//当有用户连接时发出join事件,指明用户ID和client对象
	channel.emit('join',id,client);
	client.on('data',data=>{
		data = data.toString();
		//当有用户发送数据时,发出一个频道broadcast事件,指明用户id信息
		channel.emit('broadcast',id,data);
	});
});
server.listen(8888);

    在用户关闭连接离开聊天室后,原来那个监听器还在,仍会尝试向已经断开的连接写数据就会出错。为了解决这个问题,还要按照下面的代码清单把监听器添加到频道事件发射器上,并且向服务器的 close 事件监听器中添加发射频道的leave 事件的处理逻辑。leave 事件本质上就是要移除原来给客户端添加的 broadcast 监听器。

//telchannel.js
//用 EventEmitter 实现自己的发布/预订逻辑,做一个通信通道。
const events = require('events');
const net = require('net');
const channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};
channel.on('join',function(id,client){
	const welcome =
	`Welcom!Guests online:${this.listeners('broadcast').length}`;
	client.write(`${welcome}\n`);
	//添加join事件的监听器,保存用户的client对象
	this.clients[id] = client;
	this.subscriptions[id] = (senderId,message)=>{
		if(id!=senderId){//忽略发送者
			this.clients[id].write(message);
		}
	};
	//添加一个专门针对当前用户的broadcast事件监听器
	this.on('broadcast',this.subscriptions[id]);
});
channel.on('leave',function(id){
	//leave事件的监听器
	channel.removeListener('broadcast',this.subscriptions[id]);
	//移除指定客户端的broadcast监听器
	channel.emit('broadcast',id,`${id} has left.\n`);
});
channel.on('shutdown',()=>{
	channel.emit('broadcast','','The server has shut down.\n');
	channel.removeAllListeners('broadcast');
});
const server = net.createServer(client=>{
	const id = `${client.remoteAddress}:${client.remotePort}`;
	//当有用户连接时发出join事件,指明用户ID和client对象
	channel.emit('join',id,client);
	client.on('data',data=>{
		data = data.toString();
		if(data==='shutdown\r\n'){
			channel.emit('shutdown');
		}
		//当有用户发送数据时,发出一个频道broadcast事件,指明用户id信息
		channel.emit('broadcast',id,data);
	});
	client.on('close',()=>{
		//当用户断开时发出leave事件
		channel.emit('leave',id);
	});
});
server.listen(8888);

     此处shutdown不好使,怀疑为在传输data时'shutdown'被按字母依次发送's','h'故不能检测到。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值