|
|
本文默认您已掌握react生态开发的相关技术,并熟练应用umiJS的原则上,请继续!7 K' {, D$ O5 j: g( U* G
项目需求:
! C% x$ c, W- B* H- j
9 l0 H" r; G* A" |. o1、服务侧推送给消息给前端,前端需要展示在右下角+ @+ b- Z; D5 \/ a
2、根据不同的消息类型,提供不同的操作按钮‘同意’、‘拒绝’等# I" ^1 E% V2 r+ P: q4 K
代码设计:# o8 k5 C+ f& }; F. x% s3 K4 Q
' c0 R0 k( d0 x7 {3 f
1、使用websocket方式建立通道
8 Q/ \% ~0 m4 y& g! y2、前端基于umi+antd+reconnecting-websocket.js开发! p z6 t/ Q+ Q
3、使用express+express-ws+mockjs建立websocket服务通道,模拟服务端推送消息7 _7 K) L( N7 g0 e
运行效果:
N8 z- Z4 e& h
6 }: _! }, v& n; {8 D* [9 b! O0 P5 w4 R( O+ [
2 x0 w" X9 `9 k: k. m* u& j
& \$ @+ z0 O6 N" j6 ]* U使用方法:
- z* U- r. _6 m; k& w1 P$ R. v. `
& Y, ] _ Q" j* }0 J1、项目中已引入reconnecting-websocket.min.js,详见其官方文档8 \: W% y6 s, e) o5 B& z
2、登录成功后,接着调用websocket初始化:- yield put({ type: 'websocket/init', payload: { authToken }});
复制代码 核心代码:
% z# w" F/ \3 t' H" R
; y9 p# x. M, U% J- W }. @# i1、/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组件封装,结构及代码' k8 R. `2 Y' g) r# O9 z
5 E" K7 q g' o+ C/ B7 f6 [2 g(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=this.onClose(msgId)} />; break; case 'demo2': content=this.onClose(msgId)} />; break; default: break; } notification.open({ message: {title} {time}, 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( {content}
-
- ) } } 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( {content}
-
- [list]
- [*] {this.dealApproval('agree',note.get('data'))}}>{formatMessage({id: 'Global.agree'})}
- [*] {this.dealApproval('refuse',note.get('data'))}}>{formatMessage({id: 'Global.refuse'})}
- [/list]
- ) } } NotificationSon.propTypes = { }
复制代码 express模拟消息:
' Q, c' Q% j. Q( A' `: E' k6 z; h! o% Q3 n! u
到此这篇关于前端监听websocket消息并实时弹出的文章就介绍到这了,更多相关websocket消息监听内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!
) e/ o6 o( K. t
8 N, @9 P( n; K4 j- ]/ [' s. y来源:http://www.jb51.net/html5/798933.html
- z" a& o* i2 x; X& `# F免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|