主要是想玩,想了解一下webSocket。
https://www.liaoxuefeng.com/wiki/1022910821149312/1103332447876608【编写聊天室】
https://www.ruanyifeng.com/blog/2017/05/websocket.html【WebSocket教程】
逻辑梳理:
前端
页面初始化后
1、请求返回数据库记录的所有聊天记录,通过computed整理数据结构
2、通过fingerprintjs生成用户唯一uid,在手动生成一个默认名称,然后写入cookie,向服务器发起连接请求
3、通过onmessage监听,当收到来自服务器的信息时,核对当前信息是否是对应uid,是的话则发起请求记录当前记录到数据库
后端
koa+koa-router+sequelize+ws
1、将koa的app.listen(2224)返回的http.Server用来批量创建WebSocketServer,这样就可同个端口,多个处理
2、监听connection,传入参数ws,则为此时的所有创建的分机
3、参数ws监听message,如果有信息传入,则轮询当前wss实例的所有客户机clients,发送
注意事项:
主要代码
前端
let initUser = (fn)=>{let user = Cookie.get('chatroomUser')if(user === ''){//通过fingerprintjs生成当前用户95%唯一idlet fpPromise = fingerprintjs.load()fpPromise.then(fp => fp.get()).then(result => {user = JSON.stringify({uid : result.visitorId,name : `匿${Random.String(3)}`,})Cookie.set('chatroomUser',encodeURI(user),10)fn(user)})}else{fn(user)}}let ws = nullinitUser(user=>{ws = new WebSocket(api.WSURL)//响应onmessage事件ws.onmessage = msg => {let json = JSON.parse(msg.data)let {uid} = JSON.parse(user)if(json.uid === uid){json.load = true //显示加载框//只有是当前用户发的信息才进行上传api.messageAdd(json,res=>{console.log(res)data.chatData.forEach(item =>{if(item.dateTime === res.dateTime){item.load = false}})})}data.chatData.push(json)//console.log(json);}//向服务器发送字符串ws.onopen = (evt)=>{console.log(`WebSocket建立连接成功!`,user);data.hint = {color : '#3e7fe2',text : '您已进入2c匿名聊天室'}}})
后端
//导入webSocket模块const WebSocket = require('ws');const { parse } = require('path');//引用Server类const WebSocketServer = WebSocket.Server;function createWebSocketServer(){//实例化let wss = new WebSocketServer({server: server,});wss.broadcast = function broadcast(data){//broadcast函数会轮询当前wss实例的所有客户机clientswss.clients.forEach(client => {client.send(data);})}console.log('服务已启动:ws://localhost:2224/');//监听connection事件,回调函数会传入一个WebSocket实例,表示这个WebSocket链接,//通过响应message事件,收到消息进行处理wss.on('connection',ws=>{//获取url,用于判断非ws/chat则断开连接let location = url.parse(ws.upgradeReq.url, true);console.log('[WebSocketServer] connection: ' + location.pathname);//通过upgradeReq的headers解析cookie,获取前端生成的id//console.log(ws.upgradeReq.headers);let webUser = parseUser(ws.upgradeReq.headers)onClose = function (code,message) {console.log(`closed: ${code} - ${message}`);}onMessage = message=>{//将接收到的信息分发到到所有客户机let msg = createMessage({...JSON.parse(message),...webUser,dateTime : new Date().getTime()})wss.broadcast(msg);}onError = function (err) {console.log('[WebSocket] error: ' + err);}ws.on('message',onMessage)ws.on('close',onClose)ws.on('error', onError)if(location.pathname !== '/ws/chat'){//关闭连接ws.close(4000,'Invalid URL')}})}
