我知道setTimeout不一定在您指定的确切延迟时触发,因为在超时发生的那一刻,队列中可能还有其他项目,引擎将首先执行这些操作(进一步延迟指定(。
然而,我想知道它是否真的考虑了亚毫秒的输入。例如,如果我输入1.12345678
ms,在幕后它是试图在那个确切的时间触发,还是在真正设置实际超时之前(在引擎盖下(解析我输入的亚毫秒值?
此外,假设我用长除法确定ms延迟,该除法产生类似1.2237832530049438e-9
的指数。在将指数交给setTimeout(()=>{},ms)
之前,我需要parseInt
吗?还是setTimeout
会做正确的事情(只要它是某种类型的数字(而不必担心准备输入?
更新:以下是setTimeout处理越来越小的亚毫秒延迟值的片段:
let count = 0;
function consoleLog(timeOut)
{
let now = Date.now();
timeOut = (timeOut / 1.12345);
setTimeout(()=>
{
count += 1;
if (count <= 6444)
{
console.log(`Timestamp ${now}`,`Timeout: ${timeOut}`,`Count: ${count}`);
consoleLog(timeOut);
}
});
}
consoleLog(1000);
警告,上面的代码重复了6444次,以表明timeOut值不再因进一步除以而变小:在计数6440之后,超时将维持2e-323
。
现代浏览器将setTimeout
/setInterval
调用限制为至少每4毫秒一次。
此外,MDN表示:
延迟参数转换为带符号的32位整数。这有效地将延迟限制为2147483647毫秒,因为它被指定为IDL中的带符号整数。
因此,任何毫秒的分数都不会有效。
时间不是JS规范,而是在DOM标准中指定的。
4ms由HTML5规范指定,并且在浏览器之间是一致的2010年及以后发行。之前的版本(Firefox 5.0/Thunderbird 5.0/SeaMonkey 2.2(,嵌套超时的最小超时值为10ms
但是,在Node JS中,使用的计时器是系统特定的高精度计时器。它们(系统计时器(的分辨率可以达到纳秒。如果定时器延迟保存为整数,则应该在NodeJS中进行实验。
ExceptionOr<int> DOMWindow::setTimeout(JSC::JSGlobalObject& state, std::unique_ptr<ScheduledAction> action, int timeout, Vector<JSC::Strong<JSC::Unknown>>&& arguments)
{
auto* context = scriptExecutionContext();
if (!context)
return Exception { InvalidAccessError };
// FIXME: Should this check really happen here? Or should it happen when code is about to eval?
if (action->type() == ScheduledAction::Type::Code) {
if (!context->contentSecurityPolicy()->allowEval(&state))
return 0;
}
action->addArguments(WTFMove(arguments));
return DOMTimer::install(*context, WTFMove(action), Seconds::fromMilliseconds(timeout), true);
}
根据setTimeout
的源代码,它将int
作为输入。是一个32位有符号整数。
所以,答案是否定的。它没有考虑到这一点。