Commit a13a0b0e613c4c1db199cb0613b9334c55a92648
1 parent
f7ff6604
1.修改ws重连逻辑
Showing
2 changed files
with
120 additions
and
25 deletions
src/mes/indexMes/index.js
| @@ -332,7 +332,7 @@ const useIndexMesEvent = props => { | @@ -332,7 +332,7 @@ const useIndexMesEvent = props => { | ||
| 332 | [currentContent, sModelsId, sModelType] | 332 | [currentContent, sModelsId, sModelType] |
| 333 | ); | 333 | ); |
| 334 | 334 | ||
| 335 | - const { webSocket: ws } = props.app; | 335 | + const { webSocket: ws, userinfo } = props.app; |
| 336 | const { url } = ws || {}; | 336 | const { url } = ws || {}; |
| 337 | const wsRef = useRef(ws); | 337 | const wsRef = useRef(ws); |
| 338 | useEffect(() => { | 338 | useEffect(() => { |
| @@ -343,8 +343,8 @@ const useIndexMesEvent = props => { | @@ -343,8 +343,8 @@ const useIndexMesEvent = props => { | ||
| 343 | 343 | ||
| 344 | useEffect(() => { | 344 | useEffect(() => { |
| 345 | const connectWs = () => { | 345 | const connectWs = () => { |
| 346 | - if (!wsRef.current) { | ||
| 347 | - console.log("================webSocket不存在,创建webSocket连接======================"); | 346 | + if (!wsRef.current || wsRef.current.readyState === WebSocket.CLOSED || wsRef.current.readyState === WebSocket.CLOSING) { |
| 347 | + console.log("================webSocket不存在或已关闭,创建webSocket连接======================"); | ||
| 348 | props.dispatch({ | 348 | props.dispatch({ |
| 349 | type: "app/createWebSocket", | 349 | type: "app/createWebSocket", |
| 350 | payload: { reStart: true, dispatch: props.dispatch } | 350 | payload: { reStart: true, dispatch: props.dispatch } |
| @@ -352,15 +352,7 @@ const useIndexMesEvent = props => { | @@ -352,15 +352,7 @@ const useIndexMesEvent = props => { | ||
| 352 | return; | 352 | return; |
| 353 | } | 353 | } |
| 354 | if (wsRef.current.readyState !== WebSocket.OPEN) return; | 354 | if (wsRef.current.readyState !== WebSocket.OPEN) return; |
| 355 | - const message = { | ||
| 356 | - connectTest: 'test', | ||
| 357 | - key: 'test', | ||
| 358 | - flag: 'test', | ||
| 359 | - msg: 'test', | ||
| 360 | - sId: 'test', | ||
| 361 | - showType: 'test', | ||
| 362 | - sendFrom: props.app.userinfo.sId, | ||
| 363 | - }; | 355 | + const message = { flag: "connectTest", sId: "test", sendFrom: userinfo.sId }; |
| 364 | wsRef.current.send(JSON.stringify(message)); | 356 | wsRef.current.send(JSON.stringify(message)); |
| 365 | window.wsTimer = setTimeout(() => { | 357 | window.wsTimer = setTimeout(() => { |
| 366 | console.log("================未收到Test返回消息,webSocket重新连接======================"); | 358 | console.log("================未收到Test返回消息,webSocket重新连接======================"); |
src/models/app.js
| @@ -577,44 +577,114 @@ export default { | @@ -577,44 +577,114 @@ export default { | ||
| 577 | if (userinfo.sUserLoginType) { | 577 | if (userinfo.sUserLoginType) { |
| 578 | url = `${config.ws_host}websocket/${userinfo.sId}?sLoginType=${userinfo.sUserLoginType}`; | 578 | url = `${config.ws_host}websocket/${userinfo.sId}?sLoginType=${userinfo.sUserLoginType}`; |
| 579 | } | 579 | } |
| 580 | - if (reStart) { | 580 | + if (true) { |
| 581 | // const webSocket = yield select(state => state.app.webSocket); | 581 | // const webSocket = yield select(state => state.app.webSocket); |
| 582 | // if (webSocket === null) { | 582 | // if (webSocket === null) { |
| 583 | // return null; | 583 | // return null; |
| 584 | // } | 584 | // } |
| 585 | - url = `${config.ws_host}websocket/${userinfo.sId}?reStart=true`; | 585 | + url = `${config.ws_host}websocket/${userinfo.sId}?reStart=true&createTime=${new Date().getTime()}`; |
| 586 | if (userinfo.sUserLoginType) { | 586 | if (userinfo.sUserLoginType) { |
| 587 | url = `${config.ws_host}websocket/${userinfo.sId}?reStart=true&createTime=${new Date().getTime()}&sLoginType=${userinfo.sUserLoginType}`; | 587 | url = `${config.ws_host}websocket/${userinfo.sId}?reStart=true&createTime=${new Date().getTime()}&sLoginType=${userinfo.sUserLoginType}`; |
| 588 | } | 588 | } |
| 589 | } | 589 | } |
| 590 | + // 清理旧的WebSocket连接和定时器 | ||
| 591 | + let oldWebSocket = yield select(state => state.app.webSocket); | ||
| 592 | + if (oldWebSocket) { | ||
| 593 | + // console.log('发现旧的WebSocket连接,准备清理:', oldWebSocket); | ||
| 594 | + // console.log('旧WebSocket连接状态:', oldWebSocket.readyState); | ||
| 595 | + try { | ||
| 596 | + // 移除所有事件监听器 | ||
| 597 | + oldWebSocket.onopen = null; | ||
| 598 | + oldWebSocket.onclose = null; | ||
| 599 | + oldWebSocket.onerror = null; | ||
| 600 | + oldWebSocket.onmessage = null; | ||
| 601 | + oldWebSocket.onmessageTmp = null; | ||
| 602 | + oldWebSocket.homeAction = null; | ||
| 603 | + | ||
| 604 | + // 关闭连接 | ||
| 605 | + if (oldWebSocket.readyState === WebSocket.OPEN || oldWebSocket.readyState === WebSocket.CONNECTING) { | ||
| 606 | + oldWebSocket.close(1000, '正常关闭,准备重连'); | ||
| 607 | + // console.log('已关闭旧的WebSocket连接'); | ||
| 608 | + } | ||
| 609 | + // 断开引用,帮助垃圾回收 | ||
| 610 | + oldWebSocket = null; | ||
| 611 | + console.log('旧WebSocket连接已彻底清理'); | ||
| 612 | + } catch (error) { | ||
| 613 | + console.log('关闭旧WebSocket连接时出错:', error); | ||
| 614 | + } | ||
| 615 | + } else { | ||
| 616 | + console.log('没有发现旧的WebSocket连接'); | ||
| 617 | + } | ||
| 618 | + | ||
| 619 | + // 清除所有定时器 | ||
| 620 | + clearTimeout(window.wsTimer); | ||
| 621 | + clearTimeout(config.timerServer); | ||
| 622 | + clearTimeout(config.serverTimer); | ||
| 623 | + window.wsTimer = null; | ||
| 624 | + config.timerServer = null; | ||
| 625 | + config.serverTimer = null; | ||
| 626 | + | ||
| 627 | + // 清理全局变量 | ||
| 628 | + window.wsHistoryArgs = undefined; | ||
| 629 | + window.onmessageTmp = undefined; | ||
| 590 | const reset = (ws, config1) => { | 630 | const reset = (ws, config1) => { |
| 591 | clearTimeout(config1.timerServer); | 631 | clearTimeout(config1.timerServer); |
| 592 | clearTimeout(config1.serverTimer); | 632 | clearTimeout(config1.serverTimer); |
| 593 | start(ws, config1); | 633 | start(ws, config1); |
| 594 | }; | 634 | }; |
| 595 | const start = (ws, config1) => { | 635 | const start = (ws, config1) => { |
| 636 | + if (!ws.originalSend) { | ||
| 637 | + ws.originalSend = ws.send.bind(ws); | ||
| 638 | + } | ||
| 639 | + ws.send = (...args) => { | ||
| 640 | + const value = utils.convertStrToObj(args[0], {}); | ||
| 641 | + const { | ||
| 642 | + key, | ||
| 643 | + flag, | ||
| 644 | + sendFrom, | ||
| 645 | + sId, | ||
| 646 | + } = value; | ||
| 647 | + if ((key && flag && !['release', 'noAction'].includes(flag) && sendFrom && sId) || flag === 'connectTest') { | ||
| 648 | + // 3s内没返回消息,则重新创建ws,重新发送 | ||
| 649 | + clearTimeout(window.wsTimer); | ||
| 650 | + window.wsTimer = setTimeout(() => { | ||
| 651 | + // 检查当前WebSocket连接状态 | ||
| 652 | + if (ws && ws.readyState === WebSocket.OPEN) { | ||
| 653 | + console.log('================WebSocket连接正常但超时未收到消息,重新发送信息======================'); | ||
| 654 | + // 先尝试重新发送消息,而不是直接创建新连接 | ||
| 655 | + ws.originalSend.apply(ws, args); | ||
| 656 | + } else { | ||
| 657 | + console.log('================超时未收到WebSocket消息,重新创建ws并发送信息======================'); | ||
| 658 | + window.wsHistoryArgs = args; | ||
| 659 | + ws.onmessageTmp && (window.onmessageTmp = ws.onmessageTmp); | ||
| 660 | + dispatch({ type: 'app/createWebSocket', payload: { reStart: true, dispatch } }); | ||
| 661 | + } | ||
| 662 | + }, 3000); | ||
| 663 | + } | ||
| 664 | + ws.originalSend.apply(ws, args); | ||
| 665 | + }; | ||
| 666 | + | ||
| 667 | + if (window.wsHistoryArgs) { | ||
| 668 | + ws.send(...window.wsHistoryArgs); | ||
| 669 | + window.wsHistoryArgs = undefined; | ||
| 670 | + } | ||
| 671 | + if (window.onmessageTmp) { | ||
| 672 | + ws.onmessageTmp = window.onmessageTmp; | ||
| 673 | + window.onmessageTmp = undefined; | ||
| 674 | + } | ||
| 675 | + clearTimeout(config1.timerServer); | ||
| 596 | config1.timerServer = setTimeout(() => { | 676 | config1.timerServer = setTimeout(() => { |
| 597 | const message = { sendFrom: userinfo.sId, connectTest: 'test' }; // param 存放其它参数 keyName 需要放入Redis的数据key,keyValue 需要放入Redis的数据key 的值 | 677 | const message = { sendFrom: userinfo.sId, connectTest: 'test' }; // param 存放其它参数 keyName 需要放入Redis的数据key,keyValue 需要放入Redis的数据key 的值 |
| 598 | ws.send(JSON.stringify(message)); | 678 | ws.send(JSON.stringify(message)); |
| 599 | }, config1.timeoutServer); | 679 | }, config1.timeoutServer); |
| 600 | }; | 680 | }; |
| 601 | - const oldWebSocket = yield select(state => state.app.webSocket); | ||
| 602 | const ws = new WebSocket(url); | 681 | const ws = new WebSocket(url); |
| 603 | ws.onopen = function (e) { | 682 | ws.onopen = function (e) { |
| 604 | console.log('连接上 webscoket 服务端了', e); | 683 | console.log('连接上 webscoket 服务端了', e); |
| 605 | start(ws, config); | 684 | start(ws, config); |
| 606 | - if (oldWebSocket && oldWebSocket !== ws) { | ||
| 607 | - try { | ||
| 608 | - oldWebSocket.close(); | ||
| 609 | - console.log('================已关闭旧的WebSocket连接======================'); | ||
| 610 | - } catch (error) { | ||
| 611 | - console.log('================关闭旧WebSocket连接时出错======================', error); | ||
| 612 | - } | ||
| 613 | - } | ||
| 614 | }; | 685 | }; |
| 615 | // 全局通用的自定义onmessage的方法 | 686 | // 全局通用的自定义onmessage的方法 |
| 616 | - ws.homeAction = (msg) => { | ||
| 617 | - clearTimeout(window.wsTimer); | 687 | + ws.homeAction = msg => { |
| 618 | const rtmsg = JSON.parse(msg.data); | 688 | const rtmsg = JSON.parse(msg.data); |
| 619 | if (false && rtmsg.action === 'showImg' && location.pathname.indexOf('/indexOee') < 0) { | 689 | if (false && rtmsg.action === 'showImg' && location.pathname.indexOf('/indexOee') < 0) { |
| 620 | const msgData = JSON.parse(msg.data); | 690 | const msgData = JSON.parse(msg.data); |
| @@ -678,16 +748,49 @@ export default { | @@ -678,16 +748,49 @@ export default { | ||
| 678 | } | 748 | } |
| 679 | }; | 749 | }; |
| 680 | ws.onmessage = (msg) => { | 750 | ws.onmessage = (msg) => { |
| 751 | + clearTimeout(window.wsTimer); | ||
| 752 | + window.xlyWsTimerFun && window.xlyWsTimerFun(); | ||
| 681 | reset(ws, config); | 753 | reset(ws, config); |
| 754 | + ws.onmessageTmp?.(msg); | ||
| 682 | ws.homeAction(msg); | 755 | ws.homeAction(msg); |
| 683 | }; | 756 | }; |
| 684 | ws.onclose = (e) => { | 757 | ws.onclose = (e) => { |
| 685 | /* 当客户端收到服务器端发送关闭请求,触发onclose事件 */ | 758 | /* 当客户端收到服务器端发送关闭请求,触发onclose事件 */ |
| 686 | console.log('webscoket关闭!!', e); | 759 | console.log('webscoket关闭!!', e); |
| 760 | + // 清理定时器 | ||
| 761 | + clearTimeout(window.wsTimer); | ||
| 762 | + clearTimeout(config.timerServer); | ||
| 763 | + clearTimeout(config.serverTimer); | ||
| 764 | + window.wsTimer = null; | ||
| 765 | + config.timerServer = null; | ||
| 766 | + config.serverTimer = null; | ||
| 767 | + | ||
| 768 | + | ||
| 769 | + // 自动重连 | ||
| 770 | + if (e.code !== 1000) { // 非正常关闭 | ||
| 771 | + console.log('WebSocket非正常关闭,将在5秒后尝试重连'); | ||
| 772 | + setTimeout(() => { | ||
| 773 | + dispatch({ type: 'app/createWebSocket', payload: { reStart: true, dispatch } }); | ||
| 774 | + }, 5000); | ||
| 775 | + } | ||
| 687 | }; | 776 | }; |
| 688 | ws.onerror = (e) => { | 777 | ws.onerror = (e) => { |
| 689 | /* 如果出现连接、处理、接收、发送数据异常 触发onerror */ | 778 | /* 如果出现连接、处理、接收、发送数据异常 触发onerror */ |
| 690 | console.log('webscoket异常!!', e); | 779 | console.log('webscoket异常!!', e); |
| 780 | + // 清理定时器 | ||
| 781 | + clearTimeout(window.wsTimer); | ||
| 782 | + clearTimeout(config.timerServer); | ||
| 783 | + clearTimeout(config.serverTimer); | ||
| 784 | + window.wsTimer = null; | ||
| 785 | + config.timerServer = null; | ||
| 786 | + config.serverTimer = null; | ||
| 787 | + | ||
| 788 | + | ||
| 789 | + // 自动重连 | ||
| 790 | + console.log('WebSocket出现异常,将在5秒后尝试重连'); | ||
| 791 | + setTimeout(() => { | ||
| 792 | + dispatch({ type: 'app/createWebSocket', payload: { reStart: true, dispatch } }); | ||
| 793 | + }, 5000); | ||
| 691 | }; | 794 | }; |
| 692 | yield put({ type: 'saveWebSocket', payload: { webSocket: ws } }); | 795 | yield put({ type: 'saveWebSocket', payload: { webSocket: ws } }); |
| 693 | }, | 796 | }, |