zoukankan      html  css  js  c++  java
  • vue------websocket

      Vue项目实现websocket连接步骤:

    1、安装依赖:cnpm install stompjs

                      cnpm install sockjs-client

    2、在main.js中全局注册 

    import * as socketApi from './api/socket'// socket api文件夹下新建socket.js文件
    Vue.prototype.socketApi = socketApi 

    3、socket.js文件:

    import SockJS from 'sockjs-client'
    import Stomp from 'stompjs'

    var websock = null
    var saveObj = {}
    var websocketurl = null
    var stompClient = null
    // 初始化weosocket
    function initWebSocket(url = websocketurl) {
    // ws地址 -->这里是你的请求路径
    websocketurl = url // 请求地址
    // 建立连接对象(还未发起连接)
    var socket = new SockJS(websocketurl)
    /* var socket = new SockJS(process.env.VUE_APP_BASE_API + '/Authorization=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJNSU5HIiwiZXhwIjoxNTc4NDUyNzY4LCJpYXQiOjE1Nzg0NTA5NjgsInVzZXIiOiJ7XCJwaG9uZVwiOjE4OTQ0NDQ0NDQ0LFwib3JnSWRcIjo1MDAxMDcwMDIsXCJvcmdUeXBlXCI6NSxcInJvbGVJZFwiOjQzNH0ifQ.XnStuxg3ZT8mkfORanCU_79SO4xfcG9DYrR9VdWQ7rM')
    */
    // 获取 STOMP 子协议的客户端对象
    stompClient = Stomp.over(socket)
    // 向服务器发起websocket连接并发送CONNECT帧【连接】
    stompClient.connect({}, function(frame) {
    // 订阅频道
    stompClient.subscribe('/topic/getResponse', function(response) {
       /topic/getResponse根据后台写好的名字来

    websocketonmessage(response)
    })
    // 监听通道(也得根据后台写好的来)
    stompClient.subscribe('/user/topic/channelMessage', function(response) {
    websocketonmessage(response)
    })
    })
    socket.onclose = websocketclose
    }

    // 实际调用的方法
    function sendSock(agentData, callback) {
    if (websock.readyState === websock.OPEN) {
    // 若是ws开启状态
    websocketsend(agentData)
    } else if (websock.readyState === websock.CONNECTING) {
    // 若是 正在开启状态,则等待1s后重新调用
    setTimeout(function() {
    sendSock(agentData, callback)
    }, 1000)
    } else {
    // 若未开启 ,则等待1s后重新调用
    setTimeout(function() {
    sendSock(agentData, callback)
    }, 1000)
    }
    }

    // 数据接收
    function websocketonmessage(e) {
    const data = e.body
    if (data.indexOf('{') !== -1 && data.indexOf('}') !== -1) { // 是JSON字符串
    const obj = JSON.parse(data)
    if (saveObj[obj.messageType]) { // messageType:根据后台的类型变换 ,可能是其他

    saveObj[obj.messageType](obj)
    }
    }
    }

    function proxyFunction(messageType, callback) {
    saveObj[messageType] = callback
    }

    // 数据发送
    function websocketsend(agentData) {
    websock.send(JSON.stringify(agentData))
    }

    // 关闭
    function websocketclose(e) {
    initWebSocket()
    }

    // 创建 websocket 连接
    function websocketOpen(e) {
    console.log('连接成功')
    }

    export {
    initWebSocket, // 真正调用的两个方法
    proxyFunction
    }
     
    4、调用:
    vue文件:
    <template>
    <div v-if="messageCount>0" class="em-alarm">
    <el-tooltip class="item" effect="dark" :content="content" placement="top-start">
    <el-badge :value="messageCount" style="line-height: 25px;margin-top: -5px;" @click.native="dialogTableVisible=true">
    <el-button style="padding: 8px 10px;" size="small" type="danger" class="em-alarm-btn">
    <svg-icon icon-class="alarm" class-name="alarm-icon" />
    </el-button>
    </el-badge>
    </el-tooltip>
    <el-dialog :visible.sync="dialogTableVisible" title="消息详情" width="40%" append-to-body>
    <el-table :data="messageData" border empty-text="暂无数据">
    <el-table-column type="index" width="50" :index="tableIndex" />

    <el-table-column v-for="info in tableHeader" :key="info.key" :label="info.label" :formatter="formatterFn">
    <template slot-scope="scope">
    <span>{{ scope.row[info.key] }}</span>
    </template>
    </el-table-column>
    </el-table>
    <Pagination :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" :hide-on-single-page="pageOne" @pagination="handlePaginationChange"
    @current-change="handleCurrentChange" />
    </el-dialog>
    </div>
    </template>

    <script>
    import { messageCount, messageDetails } from '@/api/schoolService/tableInfo'
    import { staticFormatterMap } from '@/utils/formatterMap'
    export default {
    name: 'SchoolAlarm',
    data() {
    return {
    dialogTableVisible: false,
    BASE_API: process.env.VUE_APP_BASE_API, //基础地址:http://......
    messageCount: '', // badge标记的值
    messageData: [], // 详情列表
    content: '', // 提示消息
    formatterMap: {},
    tableHeader: [
    {
    label: '消息标题',
    key: 'msgTitle'
    },
    {
    label: '消息类型',
    key: 'messageType'
    },
    {
    label: '消息详情',
    key: 'describeStr'
    }
    ],
    pageOne: false,
    total: 0,
    listQuery: {
    limit: 10,
    page: 1
    }
    }
    },
    created() {
    this.init()
    this.getList()
    后台的url地址:
    const token = this.$store.getters.token // 登录时自带的token(为了区分通道)从vueX中国获取的。
    // ws:neinx那边加的,要是没有ws则会自动加上一个info,通道没法连接上
        // access_token: //后端的token名字
    // sockets: 接口基本地址必须带的
    const url = this.BASE_API + '/ws/sockets?access_token=' + token
    this.socketApi.initWebSocket(url)
    this.socketApi.proxyFunction(5, (res) => { //对应socket里面的messageType
    if (res) {
    this.init() // 校徽传递通知消息后继续获取数量
    }
    })
    },
    methods: {
    init() {
    const _param = {
    messageType: 5
    }
    messageCount({
    url: '/sockets/push/queryCountAllByPageParams',
    params: _param
    }).then(response => {
    this.content = 'xxx报警'
    this.messageCount = response.data // 校内sos报警消息
    })
    },
    tableIndex(index) { // 第二页开始表格数据行号不从1开始
    return (this.listQuery.page - 1) * this.listQuery.limit + index + 1
    },
    // 分页改变:改变条数和分页
    handlePaginationChange(res) {
    this.listQuery = res
    this.getList()
    },
    // 获取详情列表数据
    getList() {
    const _params = {
    pageSize: this.listQuery.limit,
    pageNum: this.listQuery.page,
    messageType: 5
    }
    messageDetails({
    url: '/sockets/push/queryNoContentAllByPageParams',
    params: _params
    }).then(res => {
    if (res.statusCode === 200) {
    this.messageData = res.data.list
    this.total = res.data.total
    } else if (res.statusCode === 503) {
    this.$message({
    showClose: true,
    message: '没有指定消息内容哦!',
    type: 'info',
    duration: 1000
    })
    }
    })
    },
    handleCurrentChange(val) {
    },
    // 过滤字段
    formatterFn(row, column) {
    let _val = ''
    const _formatterMap = Object.assign({}, this.formatterMap, staticFormatterMap) // 动态和静态数据求交集
    console.log('过滤', _formatterMap)
    if (column.property in _formatterMap) {
    _val = _formatterMap[column.property].get(row[column.property])
    } else {
    _val = row[column.property]
    }
    return _val
    }
    }
    }
    </script>

    <style scoped lang="scss">
    .em-alarm /deep/{
    }
    .message-title {
    font-size: 16px;
    color: #333;
    font-weight: bold;
    padding-right: 8px;
    }
    .alarm-icon{
    cursor: pointer;
    font-size: 20px;
    vertical-align: middle;
    }
    .el-button--danger.em-alarm-btn{
    border-radius: 50%;
    }
    </style>
    总结:在实现的过程中没有注意nginx服务端的websocket定义的名字,于是在连接时使用了请求地址token名字加上token,直接请求,出现了请求地址正常明明正确无误,但是发送请求时地址
    的toekn名前面多了关键字info。。。。。找了很久才发现问题!
    补充:




     













    没有人能一路单纯到底,但是要记住,别忘了最初的自己!
  • 相关阅读:
    用批处理实现映射盘网络盘为固定盘符,请更改冲突的硬盘盘符
    linux下mysql寻找my.cnf顺序
    php写memcached ,c读取乱码问题[转]
    linux下boost安装方法
    解决php soap webservice 用c++ soap调用的问题[转]
    【转载】Servlet生命周期与工作原理
    【转载】深入理解Java多态性
    JSP中几个常用的参数与中文乱码问题
    获取数据库连接
    dom4j简单实例
  • 原文地址:https://www.cnblogs.com/LindaBlog/p/12169985.html
Copyright © 2011-2022 走看看