设为首页收藏本站

安徽论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 12369|回复: 0

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

[复制链接]

63

主题

483

回帖

923

积分

高级会员

Rank: 4

积分
923
发表于 2022-3-26 10:59:13 | 显示全部楼层 |阅读模式
网站内容均来自网络,本站只提供信息平台,如有侵权请联系删除,谢谢!
本文默认您已掌握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({
  2.     type: 'websocket/init',
  3.     payload: {
  4.         authToken
  5.     }
  6. });
复制代码
核心代码:

1、/service/websocket.js
  1. /**
  2. * 基于reconnecting-websocket库已引入
  3. * 封装service文件
  4. */
  5. class Websocket{

  6.   /**
  7.    * websocket逻辑
  8.    * 2021-10-28
  9.    */

  10.   constructor(){
  11.     this.websocket=null;
  12.     this.url='ws://127.0.0.1:30001/websocket-im';
  13.     this.options={
  14.       connectionTimeout: 5000,
  15.       maxRetries: 10,
  16.     };
  17.   }

  18.   init=()=>{
  19.     this.websocket = new ReconnectingWebSocket(this.url,[], this.options);
  20.   }

  21.   close=()=>{
  22.     this.websocket && this.websocket.close();
  23.   }

  24.   onMessage=(callback)=>{
  25.     this.websocket && this.websocket.addEventListener('message', (e) => {
  26.       callback&&callback(e)
  27.     });
  28.   }

  29. }

  30. const websocket = new Websocket();

  31. // 初始化连接
  32. export function openWs() {
  33.   return websocket.init();
  34. }

  35. // 关闭连接
  36. export function closeWs() {
  37.   return websocket.close();
  38. }

  39. // 监听websocket消息
  40. export function onMessage() {
  41.   let deferred;
  42.   websocket.onMessage(function(e){
  43.     if(deferred) {
  44.         deferred.resolve(e)
  45.         deferred = null
  46.     }
  47.   });
  48.   return {
  49.     message() {
  50.       if(!deferred) {
  51.           deferred = {}
  52.           deferred.promise = new Promise(resolve => deferred.resolve = resolve)
  53.       }
  54.       return deferred.promise;
  55.     }
  56.   }
  57. }
复制代码
2、/model/websocket.js

  1. /**
  2. * 封装model文件
  3. * moment、immutable、antd、nanoid组件请自行学习
  4. */
  5. import {openWs,onMessage,closeWs} from 'services/websocket'
  6. import moment from 'moment'
  7. import { Map, fromJS } from 'immutable'
  8. import { notification } from 'antd'
  9. import nanoid from 'nanoid';

  10. const initState = Map({

  11.   message:Map(), //收到的消息
  12.   
  13. });
  14. export default {
  15.   namespace: 'websocket',

  16.   state: initState,
  17.   subscriptions: {
  18.     setup({ dispatch, history }) {
  19.       dispatch({
  20.         type: 'listener'
  21.       });
  22.       return history.listen(({ pathname, query }) => {
  23.         
  24.       });
  25.     },
  26.   },
  27.   effects: {

  28.     * listener({ payload }, { take, put, call }) {
  29.       while (true) {
  30.         const { type, payload } = yield take(['logout']);
  31.         
  32.         // 监听退出系统,则关闭websocket
  33.         if (type === 'logout') {
  34.           // 关闭websocket
  35.           yield call(closeWs);
  36.           notification.destroy();
  37.           yield put({
  38.             type: 'clearAllMessage',
  39.             payload:{
  40.             }
  41.           });
  42.         }
  43.       }
  44.     },

  45.     // 启动websocket
  46.     * init ({
  47.       payload,
  48.     }, { put, call, select }) {
  49.       yield call(openWs);
  50.       const listener = yield call(onMessage);
  51.       yield put({type: 'receiveMsg', payload:{listener}});
  52.     },

  53.     // 接受消息
  54.     * receiveMsg ({
  55.         payload: {listener}
  56.     }, { call, select, put}) {
  57.         while(true){
  58.           const event = yield call(listener.message);

  59.           yield put({
  60.             type: 'progressMsg',
  61.             payload:{
  62.               msg:JSON.parse(event.data)
  63.             }
  64.           });
  65.          
  66.             
  67.         }
  68.     },

  69.     // 统筹消息
  70.     * progressMsg ({
  71.         payload: {msg}
  72.     }, { call, select, put}) {

  73.       console.log(msg)
  74.       
  75.       yield put({
  76.         type: 'addOneMessage',
  77.         payload:{
  78.           msg
  79.         }
  80.       });
  81.         
  82.     },

  83.   },
  84.   
  85.   reducers: {
  86.    
  87.     addOneMessage(state, { payload:{msg} }) {
  88.    
  89.       const msgId = nanoid()+'-'+moment().format('x');
  90.       return state.setIn(['message',msgId], fromJS({...msg,msgId}))

  91.     },

  92.     removeOneMessage(state, { payload:{msgId} }) {
  93.    
  94.       return state.deleteIn(['message',msgId])

  95.     },

  96.     clearAllMessage(state, { payload:{} }) {
  97.    
  98.       return state.setIn(['message'],Map())

  99.     },
  100.    

  101.   },
  102.   
  103. }
复制代码
3、Notification组件封装,结构及代码

(1)package.json
  1. {
  2.   "name": "Notification",
  3.   "version": "0.0.0",
  4.   "private": true,
  5.   "main": "./index.js"
  6. }
复制代码
(2) index.less
  1. .Notification{
  2.     .btns{
  3.         padding: 0;
  4.         margin: 15px 0 0 0;
  5.         list-style: none;
  6.         width: 100%;
  7.         display: flex;
  8.         justify-content: flex-end;
  9.         li{
  10.             margin-left: 10px;
  11.         }
  12.     }
  13. }
复制代码
(3)index.js
  1. /**
  2. * 右下角弹窗组件封装
  3. */
  4. import React from 'react'
  5. import { injectIntl } from 'react-intl';
  6. import moment from 'moment'
  7. import { connect } from 'dva'
  8. import { notification } from 'antd';
  9. import Demo1 from './Demo1'
  10. import Demo2 from './Demo2'

  11. @injectIntl
  12. @connect(({
  13.   websocket,
  14. }) => ({
  15.   websocket
  16. }))
  17. export default class Notification extends React.Component {

  18.   componentWillReceiveProps(nextProps) {
  19.     const {websocket,dispatch,intl, intl: { formatMessage }} = nextProps;
  20.     let message=websocket.get('message');

  21.     message.forEach((note)=>{

  22.       let object=note.getIn(['object']);
  23.       let msgId=note.getIn(['msgId']);
  24.       let title=note.getIn(['title']);
  25.       let content=note.getIn(['content']);
  26.       let format = 'YYYY-MM-DD HH:mm:ss';
  27.       let time=note.getIn(['ts'])?moment(note.getIn(['ts']), 'x').format(format):moment().format(format);

  28.       switch (object) {
  29.         case 'demo1':
  30.           content=<Demo1
  31.                                                 dispatch={dispatch}
  32.                                                 intl={intl}
  33.                                                 note={note}
  34.                                                 onClose={()=>this.onClose(msgId)}
  35.                                         />;
  36.                                         break;
  37.         case 'demo2':
  38.           content=<Demo2
  39.             dispatch={dispatch}
  40.             intl={intl}
  41.             note={note}
  42.             onClose={()=>this.onClose(msgId)}
  43.           />;
  44.           break;
  45.         default:
  46.                                         break;
  47.                         }

  48.       notification.open({
  49.         message: <span>{title} <small>{time}</small></span>,
  50.         duration:30,
  51.         key: msgId,
  52.         description:content,
  53.         placement: 'bottomRight',
  54.         onClick: () => {
  55.          
  56.         },
  57.         onClose: () => {
  58.           this.onClose(msgId);
  59.         }
  60.       });
  61.     })

  62.   }

  63.   // 关闭消息
  64.   onClose=(msgId)=>{
  65.     const {dispatch} = this.props;
  66.     dispatch({
  67.       type:'websocket/removeOneMessage',
  68.       payload:{
  69.         msgId
  70.       }
  71.     })
  72.     return notification.close(msgId);
  73.   }
  74.   
  75.   render(){
  76.     return(
  77.         null
  78.     )
  79.   }
  80.   
  81. }


  82. Notification.propTypes = {
  83.   
  84. }
复制代码
(4)Demo1.js
  1. import React from 'react'
  2. import styles from './index.less'

  3. export default class NotificationSon extends React.Component {
  4.   
  5.   render(){
  6.     const {note,intl:{formatMessage}} = this.props;
  7.     let content=note.getIn(['content']);

  8.     return(
  9.         <div className={styles.Notification}>
  10.           <div>{content}</div>
  11.         </div>
  12.     )
  13.   }
  14.   
  15. }

  16. NotificationSon.propTypes = {
  17.   
  18. }
复制代码
(5)Demo2.js
  1. import React from 'react'
  2. import styles from './index.less'
  3. import { config } from 'utils'
  4. import { Button } from 'antd';

  5. const { defaultStyleSize } = config;

  6. export default class NotificationSon extends React.Component {

  7.   dealApproval=(type,data)=>{
  8.     const {dispatch,onClose} = this.props;
  9.     if(type=='refuse'){
  10.       console.log('拒绝')
  11.       onClose();
  12.     }else if(type=='agree'){
  13.       console.log('同意')
  14.       onClose();
  15.     }
  16.    
  17.   }
  18.   
  19.   render(){
  20.     const {note,intl:{formatMessage}} = this.props;
  21.     let content=note.getIn(['content']);

  22.     return(
  23.         <div className={styles.Notification}>
  24.           <div>{content}</div>
  25.           <ul className={styles.btns}>
  26.             <li>
  27.               <Button style={{ marginLeft: '12px' }} type={'primary'} size={defaultStyleSize}  onClick={() => {this.dealApproval('agree',note.get('data'))}}>{formatMessage({id: 'Global.agree'})}</Button>
  28.             </li>
  29.             <li>
  30.               <Button style={{ marginLeft: '12px' }} type={'danger'} size={defaultStyleSize}  onClick={() => {this.dealApproval('refuse',note.get('data'))}}>{formatMessage({id: 'Global.refuse'})}</Button>
  31.             </li>
  32.           </ul>
  33.         </div>
  34.     )
  35.   }
  36.   
  37. }

  38. NotificationSon.propTypes = {
  39.   
  40. }
复制代码
express模拟消息:

到此这篇关于前端监听websocket消息并实时弹出的文章就介绍到这了,更多相关websocket消息监听内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!
                                                                                               
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
免责声明
1. 本论坛所提供的信息均来自网络,本网站只提供平台服务,所有账号发表的言论与本网站无关。
2. 其他单位或个人在使用、转载或引用本文时,必须事先获得该帖子作者和本人的同意。
3. 本帖部分内容转载自其他媒体,但并不代表本人赞同其观点和对其真实性负责。
4. 如有侵权,请立即联系,本网站将及时删除相关内容。
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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