前端监听websocket消息并实时弹出
Posted HeavyShell
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端监听websocket消息并实时弹出相关的知识,希望对你有一定的参考价值。
本文默认您已掌握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初始化:
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组件封装,结构及代码
(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模拟消息:
结束:Over
以上是关于前端监听websocket消息并实时弹出的主要内容,如果未能解决你的问题,请参考以下文章
利用websocket+Vuex完成一个实时聊天软件(前端部分)