前端项目使用websocket实现实时消息提醒功能

发布时间:2024年01月23日

前端项目使用websocket实现实时消息提醒功能

一、websocket简介

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它提供了双向的实时通信能力。相对于传统的基于 HTTP 的轮询(polling)或者长轮询(long polling)方式,WebSocket 具有更低的延迟和更高的效率,适用于实时性要求较高的场景。

实现效果:
请添加图片描述

二、 前端实现实时消息提醒基本流程

1、创建 WebSocket 连接

首先,需要在前端建立一个 WebSocket 连接。你可以使用 JavaScript 的 WebSocket 对象。以下是一个基本的连接示例:

// 从后端获取登录token和用户id
import { getInfo } from "@/api/login.js";
import { getToken } from '@/utils/auth'
// websocket地址
let host = document.location.host
// websocket实例
var ws
// 重连定时器实例
var tt
// websocket重连开关
var websocketswitch = false

// websocket对象
var websocket = {
  // websocket建立连接
  async Init() {
    // 判断浏览器是否支持websocket
    if (!'WebSocket' in window) {
      this.$modal.msgError('您的浏览器不支持WebSocket')
      return
    }

    // 获取用户id
    let res = await getInfo()
    let userId = res.user.userName
    // 创建websocket实例
     ws = new WebSocket("ws://" + host + "/websocket/message/" + userId)
    // 监听websocket连接
    ws.onopen = function () {
      // Message({
      //     type: 'success',
      //     message: 'websocket连接成功'
      // })
    }
    // 监听websocket连接错误信息
    ws.onerror = function (e) {
      // Message({
      //   message: 'websocket传输发生错误',
      //   type: 'error'
      // })
      // 打开重连
      reconnect()
    }
    // 监听websocket接受消息
    ws.onmessage = function (e) {
      //心跳消息不做处理
      if (e.data === 'ok') {
        return
      }
    }
    ws.onclose = function () {
      reconnect()
    }
  },
  disconnectWs() {
    if (ws && ws.readyState === WebSocket.OPEN) { // 确保WebSocket连接已建立且处于打开状态
      ws.close(); // 断开连接
    } else {
    }
  },
  // websocket连接关闭方法
  onClose() {
    //关闭断开重连机制
    websocketswitch = true
    ws.close()
  },
  // websocket发送信息方法
  Send(data) {
    // 处理发送数据JSON字符串
    let msg = JSON.stringify(data)
    // 发送消息给后端
    ws.send(msg)
  },
  // 暴露websocket实例
  getWebSocket() {
    return ws
  }
}

// 监听窗口关闭事件,当窗口关闭时-每一个页面关闭都会触发-扩张需求业务
window.onbeforeunload = function () {
}

// 浏览器刷新重新连接
// 刷新页面后需要重连-并且是在登录之后
if (window.performance.navigation.type == 1 && getToken()) {
  //刷新后重连
  websocket.Init()
}

// 重连方法
function reconnect() {
  // 判断是否主动关闭连接
  if (websocketswitch) {
    return
  }
  // 重连定时器-每次websocket错误方法onerror触发他都会触发
  tt && clearTimeout(tt)
  tt = setTimeout(function () {
    websocket.Init()
    websocketswitch = false
  }, 4000)
}

// 暴露对象
export default websocket

2、在组件中调用websocket方法

<template>
    <div class="message_main" @click="openDown" ref="messageBox">
        <el-badge :hidden="noticeCount > 0 ? false : true" :value="noticeCount" class="item">
            <el-popover v-model="visible" :ref="`popoverNotice`" placement="bottom-end" width="330" trigger="manual"
                :popper-options="{
                    boundariesElement: 'body',//用于控制弹出框的位置和其他选项
                    removeOnDestroy: true,
                }">
                <em class="el-icon-bell" slot="reference"></em>
                <!-- 头部选项 -->
                <el-tabs v-model="activeIndex"  class="el-menu-demo" v-if="ifShow">
                    <el-tab-pane label="消息通知" name="0" :key="activeIndex">
                        <!-- 消息内容 循环部分 -->
                        <div class="box">
                            <div class="notification_text" v-for="(item, index) in noticeData" :key="index"
                                @click="handleMessage(item)">
                                <!-- 消息内容 -->
                                <div class="text">
                                    <p class="text_content">
                                        {{ '任务名称: ' + item.name }}
                                    </p>
                                    <p class="text_content">
                                        {{ '创建时间: ' + item.createTime }}
                                    </p>
                                </div>
                                <el-badge :hidden="todo.unreadCount > 0 ? false : true" :value="todo.unreadCount"
                                    class="text_badge"></el-badge>
                            </div>
                        </div>
                    </el-tab-pane>
                </el-tabs>
            </el-popover>
        </el-badge>
    </div>
</template>
<script>
import websocket from "@/utils/socket.js";
import {changeStatus } from "@/api/message";
export default {
    data() {
        return {
            activeIndex: "0",
            ifShow: true,
            todo: [ ],
            noticeData: [ ],
            noticeCount: null,
            visible: false,
            queryParams: {
                scene: "module-message-list-web",
            },
        };
    },
    beforeCreate() {
        websocket.Init();//初始化 WebSocket
    },
    created() {
        setTimeout(() => {
            this.getWebSocket();
        }, 1000);
    },
    methods: {
        getWebSocket() {
            let ws = websocket.getWebSocket();
            // websocket.getWebSocket()这个是websocket里面方法返回ws对象(websocket.js)
            if (ws.readyState === 1) {
                websocket.Send(this.queryParams);
            }
            // 通过ws这个对象获取这个websocket里面后端推消息前端执行的方法onmessage。
            // 给他赋给我们自己方法 this.websocketonmessage
            // websocketonmessage(e); 就会执行
            ws.onmessage = (e) => {
                this.noticeCount = JSON.parse(e.data).total;
                this.noticeData = JSON.parse(e.data).rows;
            };
        },
        //弹出框显示与隐藏
        openDown() {
            this.visible = !this.visible;
        },
    },
};
</script>
  
文章来源:https://blog.csdn.net/m0_49969710/article/details/135611852
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。