setTimeout 延迟参数是否会受到亚毫秒输入的影响?
Can setTimeout's delay argument be effected at all by sub-millisecond inputs?
我知道 setTimeout 不一定会在您指定的确切延迟时触发,因为在超时发生的那一刻队列中可能还有其他项目,引擎会先做这些事情(进一步耽误你的时间
指定)。
但是,我想知道它是否确实考虑了亚毫秒输入。例如,如果我输入 1.12345678
毫秒,它会在幕后尝试在那个确切的时间触发,还是 parseInt 我在真正设置实际超时之前输入的亚毫秒值(引擎盖下)?
此外,假设我正在确定长除法的 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);
警告,上面的代码递归 6,444 次以表明超时值不再因进一步划分而变小:在计数 6440 之后,超时持续 2e-323
。
现代浏览器限制 setTimeout
/setInterval
至少每 4 毫秒调用一次。
另外,MDN 说:
The delay argument is converted to a signed 32-bit integer. This
effectively limits delay to 2147483647 ms, since it's specified as a
signed integer in the IDL.
因此,任何毫秒数都不会有效。
时间不是 JS 规范 - 它们在 DOM 标准中指定。
4 ms is specified by the HTML5 spec and is consistent across browsers
released in 2010 and onward. Prior to (Firefox 5.0 / Thunderbird 5.0 /
SeaMonkey 2.2), the minimum timeout value for nested timeouts was 10
ms.
但是在 Node JS 中,使用的定时器是 system-specific 高精度定时器。它们(系统计时器)的精度可达纳秒级。如果定时器延迟保存为整数,应该在 Node JS 中进行实验。
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 位有符号整数。
所以,答案是否定的。不考虑。
我知道 setTimeout 不一定会在您指定的确切延迟时触发,因为在超时发生的那一刻队列中可能还有其他项目,引擎会先做这些事情(进一步耽误你的时间 指定)。
但是,我想知道它是否确实考虑了亚毫秒输入。例如,如果我输入 1.12345678
毫秒,它会在幕后尝试在那个确切的时间触发,还是 parseInt 我在真正设置实际超时之前输入的亚毫秒值(引擎盖下)?
此外,假设我正在确定长除法的 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);
警告,上面的代码递归 6,444 次以表明超时值不再因进一步划分而变小:在计数 6440 之后,超时持续 2e-323
。
现代浏览器限制 setTimeout
/setInterval
至少每 4 毫秒调用一次。
另外,MDN 说:
The delay argument is converted to a signed 32-bit integer. This effectively limits delay to 2147483647 ms, since it's specified as a signed integer in the IDL.
因此,任何毫秒数都不会有效。
时间不是 JS 规范 - 它们在 DOM 标准中指定。
4 ms is specified by the HTML5 spec and is consistent across browsers released in 2010 and onward. Prior to (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2), the minimum timeout value for nested timeouts was 10 ms.
但是在 Node JS 中,使用的定时器是 system-specific 高精度定时器。它们(系统计时器)的精度可达纳秒级。如果定时器延迟保存为整数,应该在 Node JS 中进行实验。
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 位有符号整数。
所以,答案是否定的。不考虑。