angularjs $scope.$watch 遇到的问题

本文探讨了AngularJS中使用$scope.watch监听对象变化的方法,并指出当监听器内部使用$scope.$broadcast广播事件时可能引发的问题。如果在监听回调中触发广播事件,可能会导致广播事件被多次触发,进而引起执行错乱。

angularjs可以使用$scope.watch监听对象的变化

			$scope.prizeDrawRecordId = prizeDrawRecord.id;
			
			$scope.$watch('prizeDrawRecordId' , function(newValue , oldValue){
				if(oldValue != newValue)
				{
					$scope.showMask = true;
				}
			});

但是如果在监听里面用到广播事件 就会出问题

			$scope.prizeDrawRecordId = prizeDrawRecord.id;
			
			$scope.$watch('prizeDrawRecordId' , function(newValue , oldValue){
				if(oldValue != newValue)
				{
					$scope.showMask = true;
					$scope.$broadcast('FlashProductLineActive');
				}
			});



这时候就会发出 监听次数 个 ‘FlashProductLineActive’ , 使接收广播的地方会执行 监听次数 个线程 , 造成错乱。

// AI实时分析 app.directive('aiRealTimeAnalytics', function () { // 提报工单 return { restrict: 'E', replace: true, scope: { alarmData: "=" }, template: `<div class="ai-analytics-dashboard"> <div id="open_ai_analytics_dashboard" ng-click="firstWebSocket()"></div> <div id="close_ai_analytics_dashboard" ng-click="closeWebSocket()"></div> <div class="ai-analytics-line"></div> <real-time-analytics-ai ngsend-message="ngsendMessage" ng-show="alarmData.response == 0" alarm-data="alarmData" can-ask="canAsk"></real-time-analytics-ai> <real-time-analytics-record ng-show="alarmData.response == 1" ai-answer="alarmData.aiAnswer" alarm-data="alarmData"></real-time-analytics-record> </div> `, controller: function ($scope) { $scope.canAsk = true, $scope.intervalHeart = null; // DOM 元素引用 const messagesBox = document.getElementById('messagesBox'); const userInput = document.getElementById('userInput'); const sendBtn = document.getElementById('sendBtn'); const statusIndicator = document.getElementById('status'); // WebSocket 配置 let ws = null; let responseBuffer = ''; const token = getStorageToken(); const WS_ENDPOINT = `${_protocol === 'http:' ? 'ws' : 'wss'}://${_host + "/" + _apiPath}/knowledgeServer`; // 需替换为实际地址 // 初始化 WebSocket 连接 function initWebSocket() { ws = new WebSocket(WS_ENDPOINT, [token]); // 连接事件处理 ws.onopen = () => { updateUIStatus('connected', '连接已建立'); $scope.intervalHeart && clearInterval($scope.intervalHeart); $scope.intervalHeart = setInterval(_ => { ws.send(JSON.stringify('')); }, 1000) $scope.canAsk = true; }; ws.onmessage = handleMessage; ws.onerror = handleError; ws.onclose = handleClose; } // 消息处理 function handleMessage(event) { const data = JSON.parse(event.data); switch (data.isLast) { case false: responseBuffer += data.receivedMsg; updateLastMessage(markdownToHTML(responseBuffer)); break; case true: finalizeMessage(markdownToHTML(responseBuffer)); responseBuffer = ''; $scope.canAsk = true; break; case 'error': appendMessage(`系统错误: ${data.message}`, 'system'); $scope.canAsk = true; break; } } // 错误处理 function handleError(error) { console.error('WebSocket 错误:', error); updateUIStatus('error', '连接异常,正在重连...'); setTimeout(initWebSocket, 3000); } // 关闭处理 function handleClose(event) { if (!event.wasClean) return; updateUIStatus('disconnected', '连接已断开'); $scope.canAsk = false; } // 消息发送 function sendMessage() { if ($scope.canAsk) { $scope.canAsk = false; const text = userInput.value.trim(); if (!text || !ws || ws.readyState !== WebSocket.OPEN) return; const message = { businessType: 'alarm', requestType: 'question', question: text, "zpRequestId": "deepCtrl-a2eb3c18d1272ccb43c78db889a2de28", "curRequestIndex": "", "t": getStorageToken(), "modelSource": 1 }; ws.send(JSON.stringify(message)); appendMessage(text, 'user'); userInput.value = ''; createPendingMessage(); } } // 辅助函数 function appendMessage(text, type) { const messageDiv = document.createElement('div'); messageDiv.className = `message ${type}-message`; messageDiv.innerHTML = text; messagesBox.appendChild(messageDiv); messagesBox.scrollTop = messagesBox.scrollHeight; return messageDiv; } function createPendingMessage() { const pending = appendMessage(`<div class="dots"> <span>思考中</span> <span class="dot"></span> <span class="dot"></span> <span class="dot"></span> </div>`, 'ai'); pending.style.opacity = '0.6'; return pending; } function updateLastMessage(content) { const lastMsg = messagesBox.lastElementChild; if (lastMsg?.classList.contains('ai-message')) { lastMsg.innerHTML = content; messagesBox.scrollTop = messagesBox.scrollHeight; } } function finalizeMessage(content) { const lastMsg = messagesBox.lastElementChild; if (lastMsg?.classList.contains('ai-message')) { lastMsg.innerHTML = content; lastMsg.style.opacity = '1'; } } function updateUIStatus(state, message) { statusIndicator.textContent = message; statusIndicator.style.color = { connected: '#28a745', error: '#dc3545', disconnected: '#6c757d' }[state] || '#000'; } /** * 设置处理消息 */ function setDealMessage(aiAnswer) { if (aiAnswer) { let content = markdownToHTML(aiAnswer); const firstMsg = messagesBox.firstElementChild; if (firstMsg?.classList.contains('ai-message')) { firstMsg.innerHTML = content; messagesBox.scrollTop = messagesBox.scrollHeight; } } } // 事件监听 userInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') sendMessage(); }); /** * ng 发送 */ $scope.ngsendMessage = () => { sendMessage(); } //打开弹窗 $scope.firstWebSocket = () => { setDealMessage($scope.alarmData.aiAnswer); initWebSocket(); }; /** * 关闭连接 */ $scope.closeWebSocket = () => { $scope.intervalHeart && clearInterval($scope.intervalHeart); // 已关闭记录清空 const ai_record_scroller = document.getElementById('ai_record_scroller'); ai_record_scroller.innerHTML = ""; // 未关闭记录,ai对话 messagesBox.innerHTML = `<div class="message ai-message"></div>`; userInput.value = ''; // 主动关闭连接 1000 表示正常关闭 ws.close(1000, '用户主动断开'); } } } }); app.directive('realTimeAnalyticsAi', function () { // 提报工单 return { restrict: 'E', replace: true, scope: { alarmData: "=", canAsk: "=", ngsendMessage: "=" }, template: `<div> <div class="ai-analytics-title">AI实时分析 <span>由 DeepSeek 驱动</span></div> <div class="chat-container"> <div class="status-indicator hide" id="status">连接中...</div> <div class="messages-box" id="messagesBox"> <div class="message ai-message"></div> </div> <div class="input-area"> <div class="input-group"> <input type="text" id="userInput" placeholder="支持深度追问分析" ng-disabled="!canAsk"> <button id="sendBtn" ng-click="ngsendMessage()" ng-disabled="!canAsk"><div class="ai-analytics-send"></div>发送</button> </div> </div> </div> `, controller: function ($scope) { } } }) app.directive('realTimeAnalyticsRecord', function () { // 提报工单 return { restrict: 'E', replace: true, scope: { aiAnswer: "=", alarmData: "=" }, template: `<div> <div class="ai-analytics-title">处理详情 <span>由 deepseek 驱动</span></div> <div class="ai-analytics-record"> <div id="ai_record_scroller" class="ai-record-scroller"> </div> <div class="ai-record-deal"> <span data-language="alarm.unclosed_alarms.dialog.processing_record" data-language-format="{0}:">处理记录:</span> <span ng-bind="dealResult(alarmData)" ng-class="alarmData.alarmCloseRemark?'decoration-blue':''"></span> </div> </div> </div> `, controller: function ($scope) { const ai_record_scroller = document.getElementById('ai_record_scroller'); $scope.setAIAnswer = () => { if ($scope.aiAnswer) { ai_record_scroller.innerHTML = markdownToHTML($scope.aiAnswer); ai_record_scroller.style.opacity = '1'; } } $scope.$watch('aiAnswer', function () { $scope.setAIAnswer(); }) /** * 处理结果 */ $scope.dealResult = function (alarm) { if (alarm.status == 1) { return languageSwitch('alarm.unclosed_alarms.dialog.auto_recovery'); } else if (alarm.alarmCloseTime != null) { return alarm.alarmCloseRemark ? languageSwitch('alarm.alarm_overview.table.manual_close') + '(' + alarm.alarmCloseRemark + ')' : languageSwitch('alarm.alarm_overview.table.manual_close'); } else if (alarm.configRuleTypeEditTime != null) { return alarm.alarmCloseRemark ? languageSwitch('alarm.alarm_overview.table.alarm_type_adjustment') + '(' + alarm.alarmCloseRemark + ')' : languageSwitch('alarm.alarm_overview.table.alarm_type_adjustment'); } else { return ""; } }; } } }) 兼容chorme 74.0.3792.6版本
07-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值