You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过变量存储的实例名调用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实例统一存入一个全局对象,而非直接挂载在全局作用域的零散变量上。

修改步骤

  1. 调整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;
    } %>
    
  2. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 01:02:38