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

AngularJS全局计数器/自增ID重复错误问题排查

问题分析与解决方案

嘿,我来帮你捋捋这个问题——你以为靠唯一ID就能摆脱track by $index,结果还是踩了坑,核心问题不是ID生成逻辑的问题,而是你处理对象引用的方式出了岔子。

问题到底出在哪?

先拆解你的代码逻辑:

  1. 你的helper服务生成ID的逻辑是没问题的——AngularJS的服务是单例模式,globalUniqueId会在服务初始化时创建,每次调用getNextId()都会递增,返回的确实是唯一值。
  2. 坑出在anotherService.AddRecord的实现和你传递mydata的方式上:
    • 当你调用anotherService.AddRecord(helper.getNextId(), mydata)时,你传的是mydata的对象引用,不是新的对象副本。
    • 要是你的代码里存在重复传入同一个mydata对象的情况(比如循环里复用了同一个对象变量),那每次调用AddRecord时,你修改的都是同一个对象的id属性,还把这个对象多次塞进myarray里。
    • 最后myarray里会有多个指向同一个对象的引用,它们的id会被最后一次赋值覆盖,导致ng-repeat识别到重复的id(多个项的id值一模一样),自然就抛出重复错误了。

举个直观的例子模拟这个场景:

// 假设你这么调用:
let mydata = {name: "test"};
anotherService.AddRecord(helper.getNextId(), mydata); // 此时mydata.id=1,数组里存的是这个对象
anotherService.AddRecord(helper.getNextId(), mydata); // 此时mydata.id=2,数组里的两个项的id全变成2了!

这时候数组里的两个元素其实是同一个对象,它们的id最终都是2,ng-repeat用id跟踪时当然会觉得是重复项。

怎么修复?

有两种简单的修复方式,选哪种看你的场景:

方式一:在AddRecord里创建数据副本

修改anotherService.AddRecord,每次添加时都创建mydata的副本,这样就不会修改原对象影响已经存入数组的项:

AddRecord(id, mydata){ 
    // 用扩展运算符创建副本(ES6+支持)
    let newRecord = {...mydata}; 
    // 要是环境不支持扩展运算符,就用Object.assign:let newRecord = Object.assign({}, mydata);
    newRecord.id = id; 
    myarray.push(newRecord); 
}

方式二:确保每次传入的都是新对象

在调用AddRecord之前,每次都生成新的mydata对象,别复用同一个引用:

// 比如在循环里这么写:
for (let item of someList) {
    // 每次都创建新对象
    let mydata = {name: item.name, value: item.value};
    anotherService.AddRecord(helper.getNextId(), mydata);
}

验证一下

你可以在添加完数据后打印myarray看看:

console.log(myarray);

如果里面多个项的id相同,而且控制台展开后显示它们是同一个对象(内存地址一致),那就坐实了咱们的结论。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:33:56