本文默认您已掌握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模拟消息:

到此这篇关于前端监听websocket消息并实时弹出的文章就介绍到这了,更多相关websocket消息监听内容请搜索代码网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持代码网!
发表评论