比较懒,好久没写博客了,昨天遇到个问题随手记录一下
以前没遇到这个问题,一直以为时间戳是可以作为类似于主键一样的唯一标识。直到昨天遇到个老项目,出了个奇怪的bug。
项目是别人做的老项目,我们在修改,昨天测试告知说某输入框,有时候能输入东西,有时候内容会被清空。
看了页面,清空的很明显是表单验证控件类型错误,本来该是单纯必填的文本,变成了数字。问题在于这个有时候会变,有时候不会。
该开始对于问题的定位方向不对,以为是所用插件版本过老,插件的问题。
费老大劲查看压缩的代码、跟断点,却发现所有调用控件的,都是有控件特定class的元素,并没有问题,然后怀疑不是插件问题,是调用之前就出问题了。
在插件数字控件numberbox初始化的地方用了console.trace(),查看调用栈
发现第一次非控件调用文件是utils.js 进去以后查看代码,果然发现了问题
function initValidatebox(parent) { var children = parent.find(".easyui-validatebox,.easyui-combobox,.easyui-combo,.easyui-combotree,.easyui-combogrid,.easyui-numberbox,.easyui-datebox,.easyui-datetimebox,.easyui-spinner,.easyui-numberspinner,.easyui-timespinner"); if (children && children.length > 0) { $.each(children, function(i, n) { if ($(n).attr("data-options")) { var vali_rule = eval("[{" + $(n).attr("data-options") + "}]")[0]; var ntime = new Date().getTime(); $(n).attr("autovali", ntime); var ecss = []; var csss = $(n).attr("class").split(" "); $.each(csss, function(ci, css) { if (css.indexOf("easyui") > -1) { ecss.push(css.replace("easyui-", "")); } }); if (ecss && ecss.length > 0) { $.each(ecss, function(ci, css) { try { eval("$('[autovali="" + $(n).attr("autovali") + ""]')" + "." + css).apply($('[autovali="' + $(n).attr("autovali") + '"]'), [ vali_rule ]); } catch (e) { } }); } } }); } }
//方法不复杂,关键在于下面的几行代码 var ntime = new Date().getTime(); $(n).attr("autovali", ntime); . . . eval("$('[autovali="" + $(n).attr("autovali") + ""]')" + "." + css).apply($('[autovali="' + $(n).attr("autovali") + '"]'), [ vali_rule ]); //可以看到加了一个属性,值为时间戳。"." + css 和apply是调用插件和绑定对象,这不是重点,重点是他选择元素的的使用使用时间戳为选择依据
意识到问题所在,验证是否正确。把断点打在这个方法里,多次触发,直到出现bug时慢慢跟。顿时发现错误原因
原来,在代码中时间戳并不唯一。应该是现如今电脑运行速度已经很快,循环中两个相邻元素加上的时间戳有可能一样。
这就导致了当循环到第二个元素(市场价),给其初始化时,$('[autovali="" + $(n).attr("autovali") + ""]')选择了两个元素,
从而导致前一个元素(属性名称)使用的控件种类(文本),被后一个元素的控件种类(数字)覆盖。也就导致了时隐时现的bug。毕竟并不是每一次循环都出现相邻元素加上的时间戳一样。
问题找到就好解决了,我选择最省时省力的
//$(n).attr("autovali", ntime); $(n).attr("autovali", ntime + "" + Math.floor(Math.random()*1000)); //把标识由时间戳,改为时间戳加随机1-3位的数字
总结,时间戳并不适合单独作为唯一标识,尤其是循环中加的时间戳