express+websocket implements a simple chat room

Write the background interface

1. Introduce express and express-ws

```
npm install express express-ws
```

2. Write the chat room interface

Brief description:
1. First introduce ws
2. Create a connection
3. Each user has a conn, then store the conn in the array to facilitate the broadcast of received messages in the future to convey to other users.
4. Make a statistics on the number of users
5. Receive the user name set from the front end
6. The data format is unified

obj={
	type:'name'|'count'|'message';
	data:''
}

code show as below:

const express = require("express");
const expressWs = require("express-ws");
const router = express.Router();
expressWs(router);

let count = 0;
//存放所有连接的用户
let connections = [];
router.ws('', conn => {
    //每个用户都有一个conn
    count++;
    console.log(`游客进入聊天室,当前在线人数${count}`);
    sendMsg(conn, 'count', count);
    broadcast(JSON.stringify({ type: 'count', data: count }));
    //接收用户发来的数据
    conn.on('message', function(msg) {
            let obj = JSON.parse(msg);
            if (obj.type === 'name') {
                conn.userName = obj.data;
                connections.push(conn);
                console.log(`用户的名字为${conn.userName},当前在线人数${count}`);
                sendMsg(conn, 'name', conn.userName);
                broadcast(JSON.stringify({ type: 'toast', data: `${conn.userName}进入了聊天室` }));
            } else if (obj.type === 'message') {
                broadcast(JSON.stringify({ type: 'message', data: obj.data, userName: conn.userName }))
            }
        })
        //监听关闭状态
    conn.on('close', function() {
        count--;
        broadcast(JSON.stringify({ type: 'count', data: count }));
        broadcast(JSON.stringify({ type: 'toast', data: `${conn.userName}离开了聊天室,当前在线人数${count}` }));
        console.log(`用户:${conn.userName ? conn.userName :'游客'}离开了聊天室,当前在线人数${count}`);
    })
})


function broadcast(msg) {
    // 群发消息给所有用户
    connections.forEach(item => {
        item.send(msg)
    })
}
//单独发送给一个用户
function sendMsg(conn, type, data) {
    conn.send(JSON.stringify({ type: type, data: data }));
}

module.exports = router;

3. Set the route to /ws/many

const manyWs = require('./many-ws');
app.use('/ws/many', manyWs);

front-end logic

insert image description here
insert image description here
insert image description here

代码如下:
    btn.onclick = function() {
        userName = userName.value;
        let obj = {
            type: 'name',
            data: userName
        }
        obj = JSON.stringify(obj);
        ws.send(obj);
        namePanel.style.display = 'none';
    }
	//传后台
    ws.onmessage = function(res) {
        let obj = JSON.parse(res.data);
        if (obj.type === 'name') {
            userNameSpan.innerHTML = obj.data;
        } else if (obj.type === 'count') {
            peopleNum.innerHTML = obj.data;
            console.log(obj)
        } else if (obj.type === 'toast') {
            msgCon.innerHTML += addToast(obj.data);
            msgCon.scrollTo({
                top: msgCon.scrollHeight,
                behavior: "smooth",
            });
        } else if (obj.type === 'message') {
            obj.userName === userName ? textHtml('right', obj.data) : textHtml('left', obj.data);
        }

    }

    textarea.onkeyup = function(e) {
        let val = textarea.value;
        if (e.keyCode === 13) {
            if (val.trim() !== "") {
                ws.send(JSON.stringify({
                    type: 'message',
                    data: val
                }));
                textarea.value = '';
            } else {
                tips.style.display = "block";
                setTimeout(() => {
                    tips.style.display = "none";
                }, 1000);
            }
        }
    };

    backBtn.onclick = function() {
        location.href = "http://localhost:3001"
    }

    function addToast(data) {
        return `<div class="panel-toast">${data}</div>`
    }

    function textHtml(position, text) {
        let str = '';
        if (position === "left") {
            str = `<div class="msg msg-${position}">
        <img src="./img/${position==='left'?'dufu':'libai'}.png" alt="">
        <section>
            <span>${text}</span>
            </section>
        </div>;`;
        } else if (position === "right") {
            str = `
        <div class="msg msg-right">
            <section>
                <span>${text}</span>
            </section>
            <img src="./img/libai.png" alt="">
        </div>`;
        }
        msgCon.innerHTML += str;
        msgCon.scrollTo({
            top: msgCon.scrollHeight,
            behavior: "smooth",
        });
    }

If Xiaobai doesn't like it, don't spray it, I won't release the style code, and design it by myself =-=

Guess you like

Origin blog.csdn.net/DragonOfMoon/article/details/125517816