前端监听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 window对象的top、parent、opener含义介绍
Dec 03 Javascript
JQuery与Ajax调用新浪API获取短网址的代码
Feb 07 Javascript
JavaScript中使用typeof运算符需要注意的几个坑
Nov 08 Javascript
JavaScript的面向对象编程基础
Aug 13 Javascript
JavaScript生成SQL查询表单的方法
Aug 13 Javascript
jQuery中的insertBefore(),insertAfter(),after(),before()区别介绍
Sep 01 Javascript
Knockout结合Bootstrap创建动态UI实现产品列表管理
Sep 14 Javascript
微信小程序 条件渲染详解
Oct 09 Javascript
Angular 4.x+Ionic3踩坑之Ionic 3.x界面传值详解
Mar 13 Javascript
基于Vue插入视频的2种方法小结
Apr 02 Javascript
node命令行工具之实现项目工程自动初始化的标准流程
Aug 12 Javascript
JS Html转义和反转义(html编码和解码)的实现与使用方法总结
Mar 10 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+JS+rsa数据加密传输实现代码
2011/03/23 PHP
探讨如何把session存入数据库
2013/06/07 PHP
php生成Android客户端扫描可登录的二维码
2016/05/13 PHP
PHP自带方法验证邮箱、URL、IP是否合法的函数
2016/12/08 PHP
PHP安装BCMath扩展的方法
2019/02/13 PHP
PHP实现获取毫秒时间戳的方法【使用microtime()函数】
2019/03/01 PHP
在一个浏览器里呈现所有浏览器测试结果的前端测试工具的思路
2010/03/02 Javascript
jquery ajax同步异步的执行最终解决方案
2013/04/26 Javascript
js弹出div并显示遮罩层
2014/02/12 Javascript
jquery新的绑定事件机制on方法的使用方法
2014/04/15 Javascript
jquery插件jquery.beforeafter.js实现左右拖拽分隔条对比图片的方法
2015/08/07 Javascript
jQuery实现伪分页的方法分享
2016/02/17 Javascript
jQuery验证插件validate使用方法详解
2020/09/13 Javascript
jquery实现文本框的禁用和启用
2016/12/07 Javascript
Vuex利用state保存新闻数据实例
2017/06/28 Javascript
node中的session的具体使用
2018/09/14 Javascript
关于vue状态过渡transition不起作用的原因解决
2019/04/09 Javascript
javascript事件监听与事件委托实例详解
2019/08/16 Javascript
node koa2 ssr项目搭建的方法步骤
2020/12/11 Javascript
[00:37]DOTA2上海特级锦标赛 OG战队宣传片
2016/03/03 DOTA
[03:06]3分钟带你回顾DOTA2完美盛典&完美大师赛
2017/12/06 DOTA
[01:18]PWL开团时刻DAY10——一拳超人
2020/11/11 DOTA
python静态方法实例
2015/01/14 Python
Python生成随机MAC地址
2015/03/10 Python
对Python3中的print函数以及与python2的对比分析
2018/05/02 Python
python中多层嵌套列表的拆分方法
2018/07/02 Python
Python数据类型之String字符串实例详解
2019/05/08 Python
keras实现基于孪生网络的图片相似度计算方式
2020/06/11 Python
matplotlib常见函数之plt.rcParams、matshow的使用(坐标轴设置)
2021/01/05 Python
荷兰街头时尚之家:Funkie House
2019/03/18 全球购物
英国现代市场:ARKET
2019/04/10 全球购物
Antonioli美国在线商店:时尚前卫奢华
2019/07/29 全球购物
Vans澳大利亚官网:购买鞋子、服装及配件
2019/09/05 全球购物
结构工程研究生求职信
2013/10/13 职场文书
12.4全国法制宣传日活动方案
2014/11/02 职场文书
党章党规党纪学习心得体会
2016/01/14 职场文书