翼度科技»论坛 编程开发 html5 查看内容

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

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
本文默认您已掌握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消息监听内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!

来源:https://www.jb51.net/html5/798933.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

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

x

举报 回复 使用道具