主要是想玩,想了解一下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,发送

注意事项:

前后端必须通过域名,不然无法获取到cookie

主要代码

前端

  1. let initUser = (fn)=>{
  2. let user = Cookie.get('chatroomUser')
  3. if(user === ''){
  4. //通过fingerprintjs生成当前用户95%唯一id
  5. let fpPromise = fingerprintjs.load()
  6. fpPromise.then(fp => fp.get()).then(result => {
  7. user = JSON.stringify({
  8. uid : result.visitorId,
  9. name : `匿${Random.String(3)}`,
  10. })
  11. Cookie.set('chatroomUser',encodeURI(user),10)
  12. fn(user)
  13. })
  14. }else{
  15. fn(user)
  16. }
  17. }
  18. let ws = null
  19. initUser(user=>{
  20. ws = new WebSocket(api.WSURL)
  21. //响应onmessage事件
  22. ws.onmessage = msg => {
  23. let json = JSON.parse(msg.data)
  24. let {uid} = JSON.parse(user)
  25. if(json.uid === uid){
  26. json.load = true //显示加载框
  27. //只有是当前用户发的信息才进行上传
  28. api.messageAdd(json,res=>{
  29. console.log(res)
  30. data.chatData.forEach(item =>{
  31. if(item.dateTime === res.dateTime){
  32. item.load = false
  33. }
  34. })
  35. })
  36. }
  37. data.chatData.push(json)
  38. //console.log(json);
  39. }
  40. //向服务器发送字符串
  41. ws.onopen = (evt)=>{
  42. console.log(`WebSocket建立连接成功!`,user);
  43. data.hint = {
  44. color : '#3e7fe2',
  45. text : '您已进入2c匿名聊天室'
  46. }
  47. }
  48. })

后端

  1. //导入webSocket模块
  2. const WebSocket = require('ws');
  3. const { parse } = require('path');
  4. //引用Server类
  5. const WebSocketServer = WebSocket.Server;
  6. function createWebSocketServer(){
  7. //实例化
  8. let wss = new WebSocketServer({
  9. server: server,
  10. });
  11. wss.broadcast = function broadcast(data){
  12. //broadcast函数会轮询当前wss实例的所有客户机clients
  13. wss.clients.forEach(client => {
  14. client.send(data);
  15. })
  16. }
  17. console.log('服务已启动:ws://localhost:2224/');
  18. //监听connection事件,回调函数会传入一个WebSocket实例,表示这个WebSocket链接,
  19. //通过响应message事件,收到消息进行处理
  20. wss.on('connection',ws=>{
  21. //获取url,用于判断非ws/chat则断开连接
  22. let location = url.parse(ws.upgradeReq.url, true);
  23. console.log('[WebSocketServer] connection: ' + location.pathname);
  24. //通过upgradeReq的headers解析cookie,获取前端生成的id
  25. //console.log(ws.upgradeReq.headers);
  26. let webUser = parseUser(ws.upgradeReq.headers)
  27. onClose = function (code,message) {
  28. console.log(`closed: ${code} - ${message}`);
  29. }
  30. onMessage = message=>{
  31. //将接收到的信息分发到到所有客户机
  32. let msg = createMessage({
  33. ...JSON.parse(message),
  34. ...webUser,
  35. dateTime : new Date().getTime()
  36. })
  37. wss.broadcast(msg);
  38. }
  39. onError = function (err) {
  40. console.log('[WebSocket] error: ' + err);
  41. }
  42. ws.on('message',onMessage)
  43. ws.on('close',onClose)
  44. ws.on('error', onError)
  45. if(location.pathname !== '/ws/chat'){
  46. //关闭连接
  47. ws.close(4000,'Invalid URL')
  48. }
  49. })
  50. }