Node 使用事件发射器实现简单的聊天室(广播功能)

该Demo, 使用事件发射器实现了聊天室中的广播功能 (用到了发布/订阅设计模式)

一步一步来从零开始, 实现这个功能

1. 事件发射器

在Node中 事件发射器(EventEmitter)是一个很重要的概念
事件发射器会触发事件, 并且在那么事件被触发的时候能处理它们

所有能触发事件的对象都是 EventEmitter 类的实例, 可见它多么的重要

创建事件发射器

const events = require('events')
const channel = new events.EventEmitter()
  1. 注册监听器(触发事件的时候, 会执行回调函数)
channel.on(eventName, callback)
  1. 触发事件
channel.emit(eventName, args)

2. 创建服务器

我们创建了一个服务器, 并监听了用户进入, 这一步很容易就能够完成

const net = require('net')

channel.on('join', function(id, client) {
    console.log(`监听到${id}号用户加入聊天室`)
})

let id = 0
const server = net.createServer((client) => {
    const gamer = ++id
    console.log(`${gamer}号用户进入聊天室`)
    channel.emit('join', gamer, client)
})
server.listen(8888)

前置工作基本完成了, 可以使用win10下的telnet来连接服务器试试看

telnet 127.0.0.1 8888

接下来要考虑多个用户加入的时候, 如何广播消息

3. 广播消息

这一步可能有些跳跃.
使用到了发布/订阅的设计模式, 还有闭包的概念

const events = require('events')
const net = require('net')

const channel = new events.EventEmitter()
// 发布/订阅
channel.clients = {}
channel.subscriptions = {}
channel.on('join', function(id, client) {
    console.log(`监听到${id}号玩家加入游戏`)
    this.clients[id] = client
    this.subscriptions[id] = (senderId, msg) => {
        // 忽略发送广播消息的用户
        if (id != senderId) {
            this.clients[id].write(msg)
            console.log(`${id}号玩家收到广播消息${msg}`)
        }
    }
    this.on('broadcast', this.subscriptions[id])
})

// 服务器中定义了两个闭包, id和gamer, 因为我们有两层函数作用域, 一个闭包是不行的
let id = 0
const server = net.createServer((client) => {
    const user = ++id
    console.log(`玩家${user}进入服务器`)
    channel.emit('join', user, client)
    client.on('data', (data) => {
        console.log(`${user}玩家发送广播消息: ${data.toString()} .`)
        channel.emit('broadcast', user, data.toString())
    })
})

server.listen(8888)

4. 优化

上面一版的代码会出现问题, 因为我们给每个用户都绑定了监听器, 当用户退出的时候, 监听器没有关闭, 就会出现错误

所以我们要在用户退出的时候, 删去与之对应的监听器

// ...
channel.on('leave', function(id) {
    console.log(`${id}号用户已经退出房间`)
    channel.removeListener('broadcast', this.subscriptions[id])
})

// ...
let id = 0
const server = net.createServer((client) => {
    const user = ++id
    console.log(`用户${user}进入服务器`)
    channel.emit('join', user, client)
    client.on('data', (data) => {
        console.log(`${user}用户发送广播消息: ${data.toString()} .`)
        channel.emit('broadcast', user, data.toString())
    })
    client.on('close', () => {
        channel.emit('leave', user)
    })
})

当客户端关闭连接的时候, 我们发射leave事件, 通知事件发射器删除事件

5. 功能测试

广播功能
在这里插入图片描述
退出房间
在这里插入图片描述
参考:
Node 文档
Node 实战第二版

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值