时间戳与唯一标识

比较懒,好久没写博客了,昨天遇到个问题随手记录一下

以前没遇到这个问题,一直以为时间戳是可以作为类似于主键一样的唯一标识。直到昨天遇到个老项目,出了个奇怪的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位的数字

总结,时间戳并不适合单独作为唯一标识,尤其是循环中加的时间戳

原文地址:https://www.cnblogs.com/liyan-web/p/7736125.html