罗田县升平网络工作室,一家专业从事网站建设的工作室

资讯论坛

 找回密码
 加入论坛

快捷登录

回帖中禁止出现的内容,违者将被直接永久禁止访问,删除ID处理 :1.违反法律法规 ,包括但不限于出现带有政治、色情、暴恐信息等内容;2.恶意攻击内容,包括但不限于:恶意攻击党和政府、辱骂跟帖者、攻击主题发布者、不服从论坛管理、挑衅管理者、挑战版规等;3.广告、推广内容,尤其出现带有病毒、恶意代码、广告链接等内容,包括但不限于:QQ号、文字QQ号、微信号、手机号、文字手机号、第三方网址、单位公司名称、网站名称等;4.回帖贴出该主题隐藏资源链接或其它主题隐藏资源链接的行为。
查看: 642|回复: 0

前端监听websocket消息并实时弹出(实例代码)

[复制链接]

664

主题

653

帖子

757

积分

社区达人

积分
757
发表于 2021-12-5 07:03:19 来自手机 | 显示全部楼层 |阅读模式
本文默认您已掌握react生态开发的相关技术,并熟练应用umiJS的原则上,请继续!
项目需求:

1、服务侧推送给消息给前端,前端需要展示在右下角
2、根据不同的消息类型,提供不同的操作按钮‘同意’、‘拒绝’等
代码设计:

1、使用websocket方式建立通道
2、前端基于umi+antd+reconnecting-websocket.js开发
3、使用express+express-ws+mockjs建立websocket服务通道,模拟服务端推送消息
运行效果:







使用方法:

1、项目中已引入reconnecting-websocket.min.js,详见其官方文档
2、登录成功后,接着调用websocket初始化:
  1. yield put({    type: 'websocket/init',    payload: {        authToken    }});
复制代码
核心代码:

1、/service/websocket.js
  1. /** * 基于reconnecting-websocket库已引入 * 封装service文件 */class Websocket{   /**   * websocket逻辑   * 2021-10-28   */   constructor(){    this.websocket=null;    this.url='ws://127.0.0.1:30001/websocket-im';    this.options={      connectionTimeout: 5000,      maxRetries: 10,    };  }   init=()=>{    this.websocket = new ReconnectingWebSocket(this.url,[], this.options);  }   close=()=>{    this.websocket && this.websocket.close();  }   onMessage=(callback)=>{    this.websocket && this.websocket.addEventListener('message', (e) => {      callback&&callback(e)    });  } } const websocket = new Websocket(); // 初始化连接export function openWs() {  return websocket.init();} // 关闭连接export function closeWs() {  return websocket.close();} // 监听websocket消息export function onMessage() {  let deferred;  websocket.onMessage(function(e){    if(deferred) {        deferred.resolve(e)        deferred = null     }  });  return {    message() {      if(!deferred) {          deferred = {}          deferred.promise = new Promise(resolve => deferred.resolve = resolve)      }      return deferred.promise;    }  }}
复制代码
2、/model/websocket.js
  1. /** * 封装model文件 * moment、immutable、antd、nanoid组件请自行学习 */import {openWs,onMessage,closeWs} from 'services/websocket'import moment from 'moment'import { Map, fromJS } from 'immutable'import { notification } from 'antd'import nanoid from 'nanoid'; const initState = Map({   message:Map(), //收到的消息  });export default {  namespace: 'websocket',   state: initState,  subscriptions: {    setup({ dispatch, history }) {      dispatch({        type: 'listener'      });      return history.listen(({ pathname, query }) => {              });    },  },  effects: {     * listener({ payload }, { take, put, call }) {      while (true) {        const { type, payload } = yield take(['logout']);                // 监听退出系统,则关闭websocket        if (type === 'logout') {          // 关闭websocket          yield call(closeWs);          notification.destroy();          yield put({            type: 'clearAllMessage',             payload:{            }          });        }      }    },     // 启动websocket    * init ({      payload,    }, { put, call, select }) {      yield call(openWs);      const listener = yield call(onMessage);      yield put({type: 'receiveMsg', payload:{listener}});    },      // 接受消息    * receiveMsg ({        payload: {listener}    }, { call, select, put}) {        while(true){          const event = yield call(listener.message);           yield put({            type: 'progressMsg',             payload:{              msg:JSON.parse(event.data)            }          });                              }    },     // 统筹消息    * progressMsg ({        payload: {msg}    }, { call, select, put}) {       console.log(msg)            yield put({        type: 'addOneMessage',         payload:{          msg        }      });            },   },    reducers: {        addOneMessage(state, { payload:{msg} }) {         const msgId = nanoid()+'-'+moment().format('x');      return state.setIn(['message',msgId], fromJS({...msg,msgId}))     },     removeOneMessage(state, { payload:{msgId} }) {         return state.deleteIn(['message',msgId])     },     clearAllMessage(state, { payload:{} }) {         return state.setIn(['message'],Map())     },       },  }
复制代码
3、Notification组件封装,结构及代码


(1)package.json
  1. {  "name": "Notification",  "version": "0.0.0",  "private": true,  "main": "./index.js"}
复制代码
(2) index.less
  1. .Notification{    .btns{        padding: 0;        margin: 15px 0 0 0;        list-style: none;        width: 100%;        display: flex;        justify-content: flex-end;        li{            margin-left: 10px;        }    }}
复制代码
(3)index.js
  1. /** * 右下角弹窗组件封装 */import React from 'react'import { injectIntl } from 'react-intl';import moment from 'moment'import { connect } from 'dva'import { notification } from 'antd';import Demo1 from './Demo1'import Demo2 from './Demo2' @injectIntl@connect(({  websocket, }) => ({   websocket}))export default class Notification extends React.Component {   componentWillReceiveProps(nextProps) {    const {websocket,dispatch,intl, intl: { formatMessage }} = nextProps;    let message=websocket.get('message');     message.forEach((note)=>{       let object=note.getIn(['object']);      let msgId=note.getIn(['msgId']);      let title=note.getIn(['title']);      let content=note.getIn(['content']);      let format = 'YYYY-MM-DD HH:mm:ss';      let time=note.getIn(['ts'])?moment(note.getIn(['ts']), 'x').format(format):moment().format(format);       switch (object) {        case 'demo1':          content=<Demo1                                                dispatch={dispatch}                                                intl={intl}                                                note={note}                                                onClose={()=>this.onClose(msgId)}                                        />;                                        break;        case 'demo2':          content=<Demo2            dispatch={dispatch}            intl={intl}            note={note}            onClose={()=>this.onClose(msgId)}          />;          break;        default:                                        break;                        }       notification.open({        message: <span>{title} <small>{time}</small></span>,        duration:30,        key: msgId,        description:content,        placement: 'bottomRight',        onClick: () => {                  },        onClose: () => {          this.onClose(msgId);        }      });    })   }   // 关闭消息  onClose=(msgId)=>{    const {dispatch} = this.props;    dispatch({      type:'websocket/removeOneMessage',      payload:{        msgId      }    })    return notification.close(msgId);  }    render(){    return(        null    )  }  }  Notification.propTypes = {  }
复制代码
(4)Demo1.js
  1. import React from 'react'import styles from './index.less' export default class NotificationSon extends React.Component {    render(){    const {note,intl:{formatMessage}} = this.props;    let content=note.getIn(['content']);     return(        <div className={styles.Notification}>          <div>{content}</div>        </div>    )  }  } NotificationSon.propTypes = {  }
复制代码
(5)Demo2.js
  1. import React from 'react'import styles from './index.less'import { config } from 'utils'import { Button } from 'antd'; const { defaultStyleSize } = config; export default class NotificationSon extends React.Component {   dealApproval=(type,data)=>{    const {dispatch,onClose} = this.props;    if(type=='refuse'){      console.log('拒绝')      onClose();    }else if(type=='agree'){      console.log('同意')      onClose();    }      }    render(){    const {note,intl:{formatMessage}} = this.props;    let content=note.getIn(['content']);     return(        <div className={styles.Notification}>          <div>{content}</div>          <ul className={styles.btns}>            <li>              <Button style={{ marginLeft: '12px' }} type={'primary'} size={defaultStyleSize}  onClick={() => {this.dealApproval('agree',note.get('data'))}}>{formatMessage({id: 'Global.agree'})}</Button>            </li>            <li>              <Button style={{ marginLeft: '12px' }} type={'danger'} size={defaultStyleSize}  onClick={() => {this.dealApproval('refuse',note.get('data'))}}>{formatMessage({id: 'Global.refuse'})}</Button>            </li>          </ul>        </div>    )  }  } NotificationSon.propTypes = {  }
复制代码
express模拟消息:


到此这篇关于前端监听websocket消息并实时弹出的文章就介绍到这了,更多相关websocket消息监听内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!

来源:http://www.jb51.net/html5/798933.html
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
打赏鼓励一下!
回复

使用道具 举报

回帖中禁止出现的内容,违者将被直接永久禁止访问,删除ID处理 :1.违反法律法规 ,包括但不限于出现带有政治、色情、暴恐信息等内容;2.恶意攻击内容,包括但不限于:恶意攻击党和政府、辱骂跟帖者、攻击主题发布者、不服从论坛管理、挑衅管理者、挑战版规等;3.广告、推广内容,尤其出现带有病毒、恶意代码、广告链接等内容,包括但不限于:QQ号、文字QQ号、微信号、手机号、文字手机号、第三方网址、单位公司名称、网站名称等;4.回帖贴出该主题隐藏资源链接或其它主题隐藏资源链接的行为。

浏览排行

(38463)2019-11-5 公共云钱包资金盘骗局揭秘: 网络传销+原始股骗局合体!

(22233)2019-12-20 12月17日 邓智天法院直播庭审疑问全解答!

(20722)2019-12-1 环保币GEC资金盘骗局最新消息: 即将崩盘!

(17244)2019-11-9 巨胸肥臀大长腿,嫩模糯美子真人COS不知火舞福利污图

(15868)2018-12-24 罗田县人民法院公布【第五批失信被执行人名单】 ...

(14972)2019-11-3 曝光!PTFX已经崩盘跑路,投资者血流成河!

(13018)2019-8-7 湖北电力网上缴费,支付宝绑定户号的初始密码是什么?

(12480)2018-10-17 罗田县人民政府“12345”市民服务热线服务指南

(11170)2019-12-11 公安定性了, 趣码是非法传销! 趣码怎么退回365元?

(11081)2019-12-15 满足你对女同事的幻想 风骚秘书阿朱销魂眼神勾魂摄魄

最新发表

[升平网络工作室]2025-8-23 [2025-08-23]罗田天气预报

[升平网络工作室]2025-8-23 西藏自治区成立60周年庆祝大会隆重举行 习近平出席大会

[升平网络工作室]2025-8-23 县委委员会召开查摆问题整改整治情况汇报会

[爱查小程序]2025-8-22 [爱查]在线听音乐操作说明

[升平网络工作室]2025-8-22 [2025-08-22]罗田天气预报

[升平网络工作室]2025-8-22 习近平率中央代表团抵达拉萨出席西藏自治区成立60周年庆祝活动

[升平网络工作室]2025-8-22 县关工委联合经济开发区开展“情系学子”助学活动 助力职工子女圆梦大学

[升平网络工作室]2025-8-21 2025年罗田县卫健系统赴高校公开招聘事业单位工作人员拟聘用人员公示公告

[升平网络工作室]2025-8-21 [2025-08-21]罗田天气预报

[升平网络工作室]2025-8-21 县安防委2025年度第三次全体(扩大)会召开

QQ|Archiver|手机版|小黑屋|资讯论坛BBS.SPW8.CN ( 鄂ICP备2021011341号-3 )|网站地图


手机扫一扫继续访问
[免责声明]
本站系本网编辑转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。
如涉及作品内容、版权和其它问题,请在30日内与本网联系,我们将在第一时间删除内容!
[声明]本站文章版权归原作者所有 内容为作者个人观点 本站只提供参考并不构成任何投资及应用建议。

进入社区 | 发表新帖 | 百度收录 |
技术提供:罗田县升平网络工作室
站长Email:admin@spw8.cn
投诉电话(刮开查看):15374567400

GMT+8, 2025-8-23 14:23 , Processed in 0.275778 second(s), 29 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表