如果延迟超过2147483648毫秒,setTimeout立即触发

问题

如果delay超过2147483648毫秒(24.8551天),该function将立即触发。

 setTimeout(function(){ console.log('hey') }, 2147483648) // this fires early setTimeout(function(){ console.log('hey') }, 2147483647) // this works properly 

我在Chrome v26和Node.js v8.21下试过了

setTimeout的上限是0x7FFFFFFF (或十进制中的2147483647

这是因为setTimeout使用一个32位整数来存储它的延迟值,所以任何高于这个值的都会导致这个问题

如果你想要一个超过X天的超时时间,你可以尝试使用setInterval而不是像这样的延迟值

 function setDaysTimeout(callback,days) { // 86400 seconds in a day var msInDay = 86400*1000; var dayCount = 0; var timer = setInterval(function() { dayCount++; // a day has passed if(dayCount == days) { clearInterval(timer); callback.apply(this,[]); } },msInDay); } 

你会像这样使用它

 setDaysTimeout(function() { console.log('Four days gone'); },4); // fire after 4 days 

由于你被限制在32位,所以只需在一个recursion函数中包装setTimeout就可以了:

 function setLongTimeout(callback, timeout_ms) { //if we have to wait more than max time, need to recursively call this function again if(timeout_ms > 2147483647) { //now wait until the max wait time passes then call this function again with //requested wait - max wait we just did, make sure and pass callback setTimeout(function(){ setLongTimeout(callback, (timeout_ms - 2147483647)); }, 2147483647); } else //if we are asking to wait less than max, finally just do regular setTimeout and call callback { setTimeout(callback, timeout_ms); } } 

这不是太复杂,应该可以扩展到JavaScript数量的限制,即1.7976931348623157E + 10308,这个毫秒数量,我们都将死去。

太使它成为你可以设置LongTimeout的能力,你可以修改函数来接受一个通过引用传递的对象,从而将范围保留callback用函数:

 function setLongTimeout(callback, timeout_ms, timeoutHandleObject) { //if we have to wait more than max time, need to recursively call this function again if(timeout_ms > 2147483647) { //now wait until the max wait time passes then call this function again with //requested wait - max wait we just did, make sure and pass callback timeoutHandleObject.timeoutHandle = setTimeout(function(){ setLongTimeout(callback, (timeout_ms - 2147483647), timeoutHandleObject); }, 2147483647); } else //if we are asking to wait less than max, finally just do regular setTimeout and call callback { timeoutHandleObject.timeoutHandle = setTimeout(callback, timeout_ms); } } 

现在,您可以调用超时,然后稍后取消它,如果您需要这样的话:

 var timeoutHandleObject = {}; setLongTimeout(function(){ console.log("Made it!");}, 2147483649, timeoutHandleObject); setTimeout(function(){ clearTimeout(timeoutHandleObject.timeoutHandle); }, 5000);