前端监听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实现Windows任务管理器的代码
Mar 27 Javascript
Eclipse去除js(JavaScript)验证错误
Feb 11 Javascript
JS图片无缝、平滑滚动代码
Mar 11 Javascript
png在IE6 下无法透明的解决方法汇总
May 21 Javascript
Node.js实现数据推送
Apr 14 Javascript
jQuery实现页面评论栏中访客信息自动填写功能的方法
May 23 Javascript
深入学习js瀑布流布局
Oct 14 Javascript
最细致的vue.js基础语法 值得收藏!
Nov 03 Javascript
bootstrap如何让dropdown menu按钮式下拉框长度一致
Apr 10 Javascript
JavaScript寄生组合式继承实例详解
Jan 06 Javascript
Vue服务器渲染Nuxt学习笔记
Jan 31 Javascript
简单的vuex 的使用案例笔记
Apr 13 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脚本的10个技巧(1)
2006/10/09 PHP
PHP操作Redis常用命令的实例详解
2020/12/23 PHP
jquery中的sortable排序之后的保存状态的解决方法
2010/01/28 Javascript
javaScript call 函数的用法说明
2010/04/09 Javascript
几个有趣的Javascript Hack
2010/07/24 Javascript
juqery 学习之六 CSS--css、位置、宽高
2011/02/11 Javascript
jquery获取iframe中的dom对象(两种方法)
2013/07/02 Javascript
表单元素与非表单元素刷新区别详细解析
2013/11/06 Javascript
现代 JavaScript 开发编程风格Idiomatic.js指南中文版
2014/05/28 Javascript
详解JavaScript中循环控制语句的用法
2015/06/03 Javascript
轻松实现Bootstrap图片轮播
2020/04/20 Javascript
js中的DOM模拟购物车功能
2017/03/22 Javascript
JS去掉字符串前后空格或去掉所有空格的用法
2017/03/25 Javascript
JS获取鼠标坐标并且根据鼠标位置不同弹出不同内容
2017/06/12 Javascript
jQuery.Form实现Ajax上传文件同时设置headers的方法
2017/06/26 jQuery
使用百度地图实现地图网格的示例
2018/02/06 Javascript
vue+element实现表单校验功能
2019/05/20 Javascript
vue-router结合vuex实现用户权限控制功能
2019/11/14 Javascript
jQuery弹框插件使用方法详解
2020/05/26 jQuery
Python中文分词实现方法(安装pymmseg)
2016/06/14 Python
Python 爬取携程所有机票的实例代码
2018/06/11 Python
python提取具有某种特定字符串的行数据方法
2018/12/11 Python
python读取图片的方式,以及将图片以三维数组的形式输出方法
2019/07/03 Python
python一些性能分析的技巧
2020/08/30 Python
Python 中如何使用 virtualenv 管理虚拟环境
2021/01/21 Python
美国著名首饰网站:BaubleBar
2016/08/29 全球购物
荷兰超市:DEEN
2018/03/14 全球购物
如何将一个描述日期或日期/时间的字符串转换为一个Date对象
2015/10/13 面试题
酒店总经理工作职责
2013/12/13 职场文书
社团招新策划书
2014/02/04 职场文书
快餐公司创业计划书
2014/04/29 职场文书
设计大赛策划方案
2014/06/13 职场文书
趣味运动会加油词
2015/07/18 职场文书
电力培训学习心得体会
2016/01/11 职场文书
《半截蜡烛》教学反思
2016/02/19 职场文书
Python编程源码报错解决方法总结经验分享
2021/10/05 Python