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

JavaScript处理JSON API数据时数组push后console.log显示异常求助

JavaScript处理JSON API事件数组push操作异常问题

问题背景

需要处理JSON API返回的和指定地址关联的嵌套事件数组,数组内包含多个事件,部分事件带有相同的时间戳。预期逻辑为:遍历数组,创建包含对应事件的新对象;如果检测到重复时间戳,就将重复的事件追加到已创建的对应新对象中。

异常表现

在将事件追加到新对象的已有事件数组环节,push操作看似执行成功,但console.log输出存在异常:预览显示数组内有2个元素,展开数组后仅存在1个元素,且前端代码处理生成的新对象时也只能读取到1个元素。

原问题代码

function processTransactions(address, json){  
  // 取data.items下的交易数组
  var transactions = json.data.items;  
  var txList = new Array();  
  // 遍历每个条目,迭代log_events数组,仅保留匹配(To或From)的条目
  for (let i=0; i<transactions.length; i++){    
    // tx为当前处理的交易
    var tx = transactions[i];    
    // 遍历当前交易的事件日志数组
    // 查找事件日志中匹配我们地址的条目
    for( let j=0; j<tx.log_events.length; j++){      
      // j为事件数组中的一个事件
      // 将该事件添加到处理后的事件列表中
      var e = tx.log_events[j];      
      var a = e.raw_log_topics;      
      var expr = new RegExp(address.substring(2));      
      // 检查地址是否包含在raw_log_events的内容中
      if (a.find(value => expr.test(value))){        
        if (txList.some(ev => ev.block_signed_at === e.block_signed_at)){          
          // txList中找到匹配对象
          console.log ("Match found using timestamp");          
          var o = txList.find( ev => ev.block_signed_at === e.block_signed_at );          
          o.events.push(e);          
          console.log(o);          
          console.log("ending match found")        
        } else {          
          // 未找到匹配,创建对象并添加到txList
          var o = {            
            block_signed_at: e.block_signed_at,            
            // 向对象添加unix时间戳,用于前端展示和排序
            block_signed_at_timestamp: new Date(e.block_signed_at).valueOf() / 1000,            
            events: []          
          }          
          o.events.push(e);          
          txList.push(o);        
        };              
      }   
    } 
  } 
  return {transactions: txList};
}

问题原因及修复方案

根因分析

  1. 控制台预览和展开内容不一致是浏览器控制台的惰性求值特性导致:打印对象时的预览是输出时刻的快照,展开对象时浏览器才会读取对象的最新状态,属于调试工具的正常表现,不是核心问题。
  2. 代码逻辑问题:
    • 变量作用域问题:使用var声明变量o,不存在块级作用域,两个分支内的变量声明会提升到函数作用域,可能出现引用覆盖。
    • 冗余遍历逻辑:先调用some判断是否存在同时间戳条目,再调用find查找对应条目,单次匹配要遍历两次txList,性能损耗的同时极端场景下可能出现两次遍历结果不一致。
    • 正则匹配风险:直接截取地址后缀生成正则,未对地址中的正则特殊字符(如.、$、*等)做转义,可能出现匹配逻辑异常,导致部分符合业务条件的事件未进入处理分支。

修复后代码

function processTransactions(address, json) {
  const transactions = json.data.items;
  const txList = [];
  // 提前转义正则特殊字符,避免匹配异常
  const addrSuffix = address.substring(2).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  const matchExpr = new RegExp(addrSuffix);

  for (let i = 0; i < transactions.length; i++) {
    const tx = transactions[i];
    for (let j = 0; j < tx.log_events.length; j++) {
      const currentEvent = tx.log_events[j];
      const logTopics = currentEvent.raw_log_topics;
      
      if (logTopics.find(value => matchExpr.test(value))) {
        // 单次查找即可判断是否存在同时间戳条目,无需两次遍历
        const existRecord = txList.find(ev => ev.block_signed_at === currentEvent.block_signed_at);
        if (existRecord) {
          existRecord.events.push(currentEvent);
        } else {
          const newRecord = {
            block_signed_at: currentEvent.block_signed_at,
            block_signed_at_timestamp: new Date(currentEvent.block_signed_at).valueOf() / 1000,
            events: [currentEvent]
          };
          txList.push(newRecord);
        }
      }
    }
  }
  return { transactions: txList };
}

调试建议

如果需要确认push操作是否执行成功,可以打印数组长度或者序列化后的数组内容,避免浏览器控制台惰性求值的干扰:

// 追加元素后打印确认
console.log('当前事件数组长度:', existRecord.events.length);
console.log('当前事件数组快照:', JSON.stringify(existRecord.events));

内容的提问来源于stack exchange,提问作者Steve

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 12:15:02