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


Posted in Javascript onNovember 27, 2021

本文默认您已掌握react生态开发的相关技术,并熟练应用umiJS的原则上,请继续!

项目需求:

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

代码设计:

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

运行效果:

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

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

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

使用方法:

1、项目中已引入reconnecting-websocket.min.js,详见其官方文档

2、登录成功后,接着调用websocket初始化:

yield put({
    type: 'websocket/init',
    payload: {
        authToken
    }
});

核心代码:

1、/service/websocket.js

/**
 * 基于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

/**
 * 封装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组件封装,结构及代码

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

(1)package.json

{
  "name": "Notification",
  "version": "0.0.0",
  "private": true,
  "main": "./index.js"
}

(2) index.less

.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

/**
 * 右下角弹窗组件封装
 */
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

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 

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消息并实时弹出的文章就介绍到这了,更多相关websocket消息监听内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章,希望大家以后多多支持三水点靠木!

 
Javascript 相关文章推荐
javascript 模拟JQuery的Ready方法实现并出现的问题
Dec 06 Javascript
html文件中jquery与velocity变量中的$冲突的解决方法
Nov 01 Javascript
js中的caller和callee属性介绍和例子
Jun 07 Javascript
Jquery实现地铁线路指示灯提示牌效果的方法
Mar 02 Javascript
AngularJs定制样式插入到ueditor中的问题小结
Aug 01 Javascript
如何学JavaScript?前辈的经验之谈
Dec 28 Javascript
jQuery实现弹窗居中效果类似alert()
Feb 27 Javascript
ES6中Array.copyWithin()函数的用法实例详解
Sep 16 Javascript
js用类封装pop弹窗组件
Oct 08 Javascript
vue this.reload 方法 配置
Sep 12 Javascript
详解Vue一个案例引发「内容分发slot」的最全总结
Dec 02 Javascript
JS中类的静态方法,静态变量,实例方法,实例变量区别与用法实例分析
Mar 14 Javascript
Vue实现跑马灯样式文字横向滚动
Nov 23 #Vue.js
利用js实现简单开关灯代码
Nov 23 #Javascript
详解Vue的列表渲染
Nov 20 #Vue.js
详解JS数组方法
Nov 20 #Javascript
详解Vue slot插槽
Nov 20 #Vue.js
详解Vue router路由
Nov 20 #Vue.js
Ajax异步刷新功能及简单案例
Nov 20 #Javascript
You might like
在PHP中使用与Perl兼容的正则表达式
2006/11/26 PHP
教你在header中隐藏php的版本信息
2016/08/10 PHP
js Html结构转字符串形式显示代码
2011/11/15 Javascript
jQuery实现点击标题输入详细信息
2013/04/16 Javascript
Js获取下拉框选定项的值和文本的实现代码
2014/02/26 Javascript
JS删除字符串中重复字符方法
2014/03/09 Javascript
JavaScript动态修改背景颜色的方法
2015/04/16 Javascript
jquery获取节点名称
2015/04/26 Javascript
你真的了解BOM中的history对象吗
2017/02/13 Javascript
浅谈Webpack打包优化技巧
2018/06/12 Javascript
浅谈webpack性能榨汁机(打包速度优化)
2019/01/09 Javascript
js的新生代垃圾回收知识点总结
2019/08/22 Javascript
layer.js之回调销毁对话框的例子
2019/09/11 Javascript
vue二选一tab栏切换新做法实现
2021/01/19 Vue.js
python实现的简单FTP上传下载文件实例
2015/06/30 Python
用Python实现筛选文件脚本的方法
2018/10/27 Python
对Python生成汉字字库文字,以及转换为文字图片的实例详解
2019/01/29 Python
使用pyecharts生成Echarts网页的实例
2019/08/12 Python
pandas中的数据去重处理的实现方法
2020/02/10 Python
Django微信小程序后台开发教程的实现
2020/06/03 Python
Java如何基于wsimport调用wcf接口
2020/06/17 Python
css3圆角边框和边框阴影示例
2014/05/05 HTML / CSS
CSS3制作炫酷的下拉菜单及弹起式选单的实例分享
2016/05/17 HTML / CSS
vivo智能手机官方商城:vivo
2016/09/22 全球购物
澳大利亚女士时装在线:Rockmans
2018/09/26 全球购物
飞利信loadrunner和软件测试笔试题
2012/09/22 面试题
新闻记者实习自我鉴定
2013/09/19 职场文书
毕业生医学检验求职信
2013/10/16 职场文书
授权委托书(公民个人适用)
2014/09/19 职场文书
广告设计专业毕业生自我鉴定
2014/09/27 职场文书
学生个人总结范文
2015/02/15 职场文书
2015年毕业实习工作总结
2015/05/29 职场文书
客户答谢会致辞
2015/07/30 职场文书
演讲稿之我的初心我的成长
2019/08/12 职场文书
Go语言带缓冲的通道实现
2021/04/26 Golang
uniapp引入支付宝原生扫码插件步骤详解
2022/07/23 Javascript