前端监听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 相关文章推荐
一些主流JS框架中DOMReady事件的实现小结
Feb 12 Javascript
JS注册/移除事件处理程序(ExtJS应用程序设计实战)
May 07 Javascript
js function定义函数的几种不错方法
Feb 27 Javascript
ext中store.load跟store.reload的区别示例介绍
Jun 17 Javascript
第一次接触神奇的Bootstrap
Oct 14 Javascript
Bootstrap基本插件学习笔记之Popover提示框(19)
Dec 08 Javascript
JS搜狐面试题分析
Dec 16 Javascript
JavaScript实现汉字转换为拼音的库文件示例
Dec 22 Javascript
Vue.js仿Metronic高级表格(二)数据渲染
Apr 19 Javascript
详解如何实现一个简单的Node.js脚手架
Dec 04 Javascript
node.js实现上传文件功能
Jul 15 Javascript
vue2.x 通过后端接口代理,获取qq音乐api的数据示例
Oct 30 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
header跳转和include包含问题详解
2012/09/08 PHP
微信支付开发维权通知实例
2016/07/12 PHP
php结合ajax实现手机发红包的案例
2016/10/13 PHP
JavaScript CSS修改学习第二章 样式
2010/02/19 Javascript
javascript的数据类型、字面量、变量介绍
2012/05/23 Javascript
JQuery处理json与ajax返回JSON实例代码
2014/01/03 Javascript
JavaScript自定义日期格式化函数详细解析
2014/01/14 Javascript
js函数定时器实现定时读取系统实时连接数
2014/04/30 Javascript
jQuery处理图片加载失败的常用方法
2015/06/08 Javascript
JS打字效果的动态菜单代码分享
2015/08/21 Javascript
ionic实现可滑动的tab选项卡切换效果
2020/04/15 Javascript
angular ng-click防止重复提交实例
2017/06/16 Javascript
angular4强制刷新视图的方法
2018/10/09 Javascript
详解Bootstrap 学习(一)入门
2019/04/12 Javascript
JavaScript回调函数callback用法解析
2020/01/14 Javascript
详解JavaScript中精度失准问题及解决方法
2020/02/04 Javascript
[28:42]Ti4正赛VG vs NEWBEE1
2014/07/19 DOTA
Python的ORM框架SQLObject入门实例
2014/04/28 Python
举例讲解Python的lambda语句声明匿名函数的用法
2016/07/01 Python
Python外星人入侵游戏编程完整版
2020/03/30 Python
Python读取Word(.docx)正文信息的方法
2018/03/15 Python
python如何制作英文字典
2019/06/25 Python
学习Django知识点分享
2019/09/11 Python
解决python3.x安装numpy成功但import出错的问题
2020/11/17 Python
英国健身超市:Fitness Superstore
2019/06/17 全球购物
大学生自我鉴定范文
2013/12/28 职场文书
技能比赛获奖感言
2014/02/14 职场文书
大学生新学期计划书
2014/04/28 职场文书
2014年巴西世界杯口号
2014/06/05 职场文书
2014年度工作总结报告
2014/12/15 职场文书
不尊敬老师的检讨书
2014/12/21 职场文书
公务员年度考核个人总结
2015/02/12 职场文书
幼儿园六一儿童节演讲稿
2015/03/19 职场文书
Java基于字符界面的简易收银台
2021/06/26 Java/Android
nginx常用配置conf的示例代码详解
2022/03/21 Servers
springboot应用服务启动事件的监听实现
2022/04/06 Java/Android