如何通过变量调用已存在的Gauge实例的setValue方法?
问题解决:通过字符串变量调用已存在的Gauge实例方法(规避eval)
错误本质
sseTopicString是字符串类型(值为"Gauge12"),字符串本身没有setValue方法;而直接写Gauge12.setValue()是调用全局作用域下的Gauge实例对象的方法,两者本质完全不同,这就是报错的核心原因。
替代eval的两种可行方案
方案1:通过全局window对象获取实例
如果Gauge实例是挂载在全局作用域(比如直接声明为全局变量),可以通过window[sseTopicString]直接获取对应实例,再调用方法:
// 替换原代码中的 sseTopicString.setValue(sseValueNumber); const targetGauge = window[sseTopicString]; // 增加存在性检查,避免报错 if (targetGauge && typeof targetGauge.setValue === 'function') { targetGauge.setValue(sseValueNumber); } else { console.warn(`未找到名为${sseTopicString}的Gauge实例,或实例无setValue方法`); }
这种方式比eval更安全,避免了eval的性能损耗和注入风险,适合实例已在全局作用域的场景。
方案2:维护自定义实例映射表(推荐)
更规范的做法是自己维护一个对象存储所有Gauge实例,彻底脱离全局作用域依赖:
// 提前在全局/模块作用域创建实例映射表 const gaugeInstances = {}; // 创建Gauge实例时,将其存入映射表(示例代码) const Gauge12 = new Gauge(/* 你的配置参数 */); gaugeInstances['Gauge12'] = Gauge12; // 在SSE回调中使用映射表获取实例 const targetGauge = gaugeInstances[sseTopicString]; if (targetGauge && typeof targetGauge.setValue === 'function') { targetGauge.setValue(sseValueNumber); }
这种方式更可控,避免全局变量污染,也方便后续对实例进行统一管理(比如销毁、遍历更新等)。
修改后的完整代码示例(以方案1为例)
let sse = new EventSource("http://localhost:3000/sse-stream"); sse.onmessage = function (event) { let jdata = JSON.parse(event.data); console.log(jdata); let rawSseTopic = jdata.topicname; let sseTopic = removeSpecialCharacters(rawSseTopic); let sseTopicString = sseTopic.toString(); console.log(sseTopicString); let sseValue = jdata.message; let sseValueNumber = Number(sseValue); console.log(sseValueNumber); // 替换原错误代码的核心逻辑 const targetGauge = window[sseTopicString]; if (targetGauge && typeof targetGauge.setValue === 'function') { targetGauge.setValue(sseValueNumber); } else { console.warn(`未找到名为${sseTopicString}的Gauge实例,或实例无setValue方法`); } }; function removeSpecialCharacters(string) { let cleanString = string.replace(/,|\.|-|_|\|\s|\//g, ""); return cleanString; }
注意事项
- 使用方案1时,要确保Gauge实例确实是全局变量(没有用
let/const在局部作用域声明)。 - 两种方案都建议增加存在性检查,避免因实例未创建或方法缺失导致的额外报错。
内容的提问来源于stack exchange,提问作者IoT-Practitioner
相关产品推荐
相关产品推荐

