我需要使用JavaScript动态生成唯一的ID号码。过去,我是通过使用时间来创建一个数字来实现这一点的。该数字由四位数年份、两位数月份、两位数日期、两位数小时、两位数分钟、两位数秒和三位数毫秒组成。因此它看起来像这样:20111104103912732... 这足以提供我所需的唯一数字的确定性。
已经有一段时间了,我没有这个代码了。是否有人可以提供这个代码,或者有更好的建议来生成唯一ID?
我需要使用JavaScript动态生成唯一的ID号码。过去,我是通过使用时间来创建一个数字来实现这一点的。该数字由四位数年份、两位数月份、两位数日期、两位数小时、两位数分钟、两位数秒和三位数毫秒组成。因此它看起来像这样:20111104103912732... 这足以提供我所需的唯一数字的确定性。
已经有一段时间了,我没有这个代码了。是否有人可以提供这个代码,或者有更好的建议来生成唯一ID?
试试这个
function generateId() {
return +new Date();
}
然后将其赋值给变量
const uniqueId = generateId();
// return a uid, sortable by creation order
let increment;
let tuidPrev;
const uid = (uidPrev) => {
// get current time to microsecond precision (if available) and remove decimals
const tuid = ((performance.timing.navigationStart + performance.now()) * 1000)
// convert timestamp to base36 string
.toString(36);
// previous uid has been provided (stateful)
if (uidPrev) {
tuidPrev = uidPrev.slice(0, 10);
increment = uidPrev.length > 10 ? parseInt(uidPrev.slice(10), 36) : 0;
}
// if tuid is changed reset the increment
if (tuid !== tuidPrev) {
tuidPrev = tuid;
increment = 0;
}
// return timed uid + suffix (4^36 values) === very unique id!
return tuid + ('000' + (increment++).toString(36)).slice(-4);
}
// EXAMPLE (check the console!)
const iterations = 1000000;
const uids = [];
const uidMap = {};
const timeMap = {}
const microMap = {};
let time = performance.now();
for (let i = 0; i < iterations; i++) {
const id = uid();
uids.push(id);
uidMap[id] = i;
timeMap[Date.now()] = i;
microMap[performance.now()] = i;
}
console.log(`Time taken: ${performance.now() - time}ms`);
console.log('Unique IDs:', Object.keys(uidMap).length.toLocaleString());
console.log('Clashing timestamps:', (iterations - Object.keys(timeMap).length).toLocaleString());
console.log('Clashing microseconds:', (iterations - Object.keys(microMap).length).toLocaleString());
console.log('Sortable:', !uids.slice().sort().find((id, i) => uids[i] !== id))
Date.now();
。const ID = Date.now();
console.log(ID);
idgp
的库,可以通过npm安装。let uuid = ((new Date().getTime()).toString(36))+'_'+(Date.now() + Math.random().toString()).split('.').join("_")
样例结果为"k3jobnvt_15750033412250_18299601769317408"
let now = new Date();
let timestamp = now.getFullYear().toString();
let month = now.getMonth() + 1;
timestamp += (month < 10 ? '0' : '') + month.toString();
timestamp += (now.getDate() < 10 ? '0' : '') + now.getDate().toString();
timestamp += (now.getHours() < 10 ? '0' : '') + now.getHours().toString();
timestamp += (now.getMinutes() < 10 ? '0' : '') + now.getMinutes().toString();
timestamp += (now.getSeconds() < 10 ? '0' : '') + now.getSeconds().toString();
timestamp += (now.getMilliseconds() < 100 ? '0' : '') + now.getMilliseconds().toString();
window.getUniqNr = function() {
var now = new Date();
if (typeof window.uniqCounter === 'undefined') window.uniqCounter = 0;
window.uniqCounter++;
var m = now.getMonth(); var d = now.getDay();
var h = now.getHours(); var i = now.getMinutes();
var s = now.getSeconds(); var ms = now.getMilliseconds();
timestamp = now.getFullYear().toString()
+ (m <= 9 ? '0' : '') + m.toString()
+( d <= 9 ? '0' : '') + d.toString()
+ (h <= 9 ? '0' : '') + h.toString()
+ (i <= 9 ? '0' : '') + i.toString()
+ (s <= 9 ? '0' : '') + s.toString()
+ (ms <= 9 ? '00' : (ms <= 99 ? '0' : '')) + ms.toString()
+ window.uniqCounter;
return timestamp;
};
window.getUniqNr();
假设@abarber提出的解决方案是一个好的解决方案,因为它使用(new Date()).getTime()
,所以它有毫秒级的时间窗口,并在此间隔内发生冲突时加上tick
,我们可以考虑使用内置的方法,正如我们在这里清楚地看到的那样:
首先,我们可以看到在使用(new Date()).getTime()
时,1/1000窗口框架中可能会发生冲突:
console.log( (new Date()).getTime() ); console.log( (new Date()).getTime() )
VM1155:1 1469615396590
VM1155:1 1469615396591
console.log( (new Date()).getTime() ); console.log( (new Date()).getTime() )
VM1156:1 1469615398845
VM1156:1 1469615398846
console.log( (new Date()).getTime() ); console.log( (new Date()).getTime() )
VM1158:1 1469615403045
VM1158:1 1469615403045
接下来我们尝试提出的解决方案,以避免在1/1000窗口中发生碰撞:
console.log( window.mwUnique.getUniqueID() ); console.log( window.mwUnique.getUniqueID() );
VM1159:1 14696154132130
VM1159:1 14696154132131
话虽如此,我们可以考虑使用像节点process.nextTick
这样的函数,在事件循环中被称为单个tick
,并且在这里有很好的解释。
当然,在浏览器中没有process.nextTick
,所以我们必须想办法解决这个问题。
这个实现将在浏览器中安装一个nextTick
函数,使用最接近浏览器I/O的函数,包括setTimeout(fnc,0)
、setImmediate(fnc)
和window.requestAnimationFrame
。正如这里所建议的那样,我们可以添加window.postMessage
,但我把它留给读者,因为它还需要一个addEventListener
。我已经修改了原始模块版本,使其更简单:
getUniqueID = (c => {
if(typeof(nextTick)=='undefined')
nextTick = (function(window, prefixes, i, p, fnc) {
while (!fnc && i < prefixes.length) {
fnc = window[prefixes[i++] + 'equestAnimationFrame'];
}
return (fnc && fnc.bind(window)) || window.setImmediate || function(fnc) {window.setTimeout(fnc, 0);};
})(window, 'r webkitR mozR msR oR'.split(' '), 0);
nextTick(() => {
return c( (new Date()).getTime() )
})
})
所以我们在1/1000的窗口中:
getUniqueID(function(c) { console.log(c); });getUniqueID(function(c) { console.log(c); });
undefined
VM1160:1 1469615416965
VM1160:1 1469615416966
添加我的看法是因为我想要一个 UID 的解决方案:
const uid = new Date().toISOString().replaceAll(/[-:TZ]/g, '.') + Math.random().toString().substring(2,7)
// '2022.04.15.03.56.36.197.50167'
注意:您可以调整子字符串的第二个参数以增加唯一性的机会,但这将使uid
变长。具体取决于您的使用情况。
简单易用,总是获得唯一值:
const uniqueValue = (new Date()).getTime() + Math.trunc(365 * Math.random());
**OUTPUT LIKE THIS** : 1556782842762
即使在快速循环内部,这也返回唯一的值。
当然,这可以进一步改进
const getUniqueValue = (strength = 2, int=false) => {
const u = () => (Math.random() * 10000).toString().replace('.','');
let r = '';
for (let i=0; i < strength; i++) {
r += u();
}
return (int) ? parseInt(r) : r;
}
[1,2,3,5,6,7,8,9,10].map(item => console.log(getUniqueValue()));
new Date().toISOString()
吗? - Anna B