如何通过变量存储的实例名调用SVG Gauge实例的setValue方法?
问题:通过SSE获取实例名称后调用方法报错,寻求替代eval的实现方案
我在前端使用SVG Gauge库的Gauge类时,静态代码直接调用实例方法完全正常:
instanceName.method(varValue);
用EJS预渲染代码也能正常控制仪表指针:
<%= gaugeInstanceVar %>.setValue(<%= gaugeValueVar %>);
但页面渲染完成后,通过Server Sent Events(SSE)拿到存储实例名称的变量,执行gaugeInstanceVar.method(varValue)时会抛出Uncaught TypeError: X.setValue is not a function错误。目前用eval()能实现需求,但想避开eval,求正确的实现方式。
补充代码
EJS生成实例的代码
<% data.forEach( element=> { switch(element.gaugetype) { case 'gauge3': gaugeClass ='gauge-container three'; // 用于div的类名 %> <script>var <%= element.topic %> = Gauge(document.getElementById('<%= element.topic %>'), { max: <%= element.value %>, value: 50 } );</script> <% break; default: return; break; } %>
SSE处理代码
// Server Sent Event 处理器 let sse = new EventSource("http://localhost:3000/sse-stream"); sse.onmessage = function (event) { let jdata = JSON.parse(event.data); let sseValue = jdata.message; let sseValueNumber = Number(sseValue); let rawSseTopic = jdata.topicname; let sseTopic = removeSpecialCharacters(rawSseTopic); sseTopic.setValue(sseValueNumber); // 类型错误:不是函数 // eval(sseTopic).setValue(sseValueNumber); 不想用这个 }; function removeSpecialCharacters(string) { let cleanString = string.replace(/,|\.|-|_|\||\s|\//g, ""); return cleanString; }
解决方案
问题核心是:你通过SSE拿到的sseTopic是字符串,不是实际的Gauge实例对象。直接调用字符串的setValue方法自然会报错,而eval是把字符串解析成变量名获取实例,所以能生效。要避开eval,建议提前把所有Gauge实例统一存入一个全局对象,而非直接挂载在全局作用域的零散变量上。
修改步骤
调整EJS代码,将实例存入全局管理对象
创建一个全局的gaugeInstances对象,所有Gauge实例都以名称为键存入该对象:<% data.forEach( element=> { switch(element.gaugetype) { case 'gauge3': gaugeClass ='gauge-container three'; // 用于div的类名 %> <script> // 确保全局管理对象存在 window.gaugeInstances = window.gaugeInstances || {}; // 将实例存入对象,键为element.topic window.gaugeInstances['<%= element.topic %>'] = Gauge(document.getElementById('<%= element.topic %>'), { max: <%= element.value %>, value: 50 }); </script> <% break; default: return; break; } %>修改SSE处理逻辑,从全局对象中获取实例
拿到清理后的sseTopic字符串后,直接从gaugeInstances对象中取出对应实例再调用方法:// Server Sent Event 处理器 let sse = new EventSource("http://localhost:3000/sse-stream"); sse.onmessage = function (event) { let jdata = JSON.parse(event.data); let sseValue = jdata.message; let sseValueNumber = Number(sseValue); let rawSseTopic = jdata.topicname; let sseTopic = removeSpecialCharacters(rawSseTopic); // 从全局管理对象中获取实例 const gaugeInstance = window.gaugeInstances[sseTopic]; if (gaugeInstance && typeof gaugeInstance.setValue === 'function') { gaugeInstance.setValue(sseValueNumber); } else { console.warn(`找不到名为${sseTopic}的Gauge实例,或实例无setValue方法`); } }; function removeSpecialCharacters(string) { let cleanString = string.replace(/,|\.|-|_|\||\s|\//g, ""); return cleanString; }
方案优势
- 彻底规避
eval带来的安全风险(如恶意字符串注入) - 所有实例统一管理,代码结构更清晰,便于后续维护和调试
- 对象属性访问的性能远高于
eval
内容的提问来源于stack exchange,提问作者IoT-Practitioner
相关产品推荐
相关产品推荐

