动态标准 — 最后更新于 2024年9月12日
setTimeout()
和 setInterval()
方法允许作者安排基于定时器的回调。
id = self.setTimeout(handler [, timeout [, ...arguments ] ])
所有当前引擎都支持。
安排一个超时,在 timeout 毫秒后运行 handler。任何 arguments 都直接传递给 handler。
id = self.setTimeout(code [, timeout ])
安排一个超时,在 timeout 毫秒后编译并运行 code。
self.clearTimeout(id)
所有当前引擎都支持。
取消由 setTimeout()
或 setInterval()
设置的,由 id 标识的超时。
id = self.setInterval(handler [, timeout [, ...arguments ] ])
所有当前引擎都支持。
安排一个超时,每隔 timeout 毫秒运行 handler 一次。任何 arguments 都直接传递给 handler。
id = self.setInterval(code [, timeout ])
安排一个超时,每隔 timeout 毫秒编译并运行 code 一次。
self.clearInterval(id)
所有当前引擎都支持。
取消由 setInterval()
或 setTimeout()
设置的,由 id 标识的超时。
定时器可以嵌套;但是,在五个这样的嵌套定时器之后,间隔将被强制为至少四毫秒。
此 API 不保证定时器会完全按计划运行。由于 CPU 负载、其他任务等原因造成的延迟是预期的。
实现 WindowOrWorkerGlobalScope
混合类的对象具有一个 setTimeout 和 setInterval ID 的映射,它是一个 有序映射,最初为空。此映射中的每个 键 都是一个正整数,对应于 setTimeout()
或 setInterval()
调用的返回值。每个 值 都是一个 唯一的内部值,对应于对象 活动定时器映射 中的一个键。
setTimeout(handler, timeout, ...arguments)
方法的步骤是返回给定 this、handler、timeout、arguments 和 false 的 定时器初始化步骤 的运行结果。
setInterval(handler, timeout, ...arguments)
方法的步骤是返回给定 this、handler、timeout、arguments 和 true 的 定时器初始化步骤 的运行结果。
clearTimeout(id)
和 clearInterval(id)
方法的步骤是 移除 this 的 setTimeout 和 setInterval ID 的映射[id]
因为 clearTimeout()
和 clearInterval()
清除同一映射中的条目,所以任何一种方法都可以用来清除由 setTimeout()
或 setInterval()
创建的定时器。
为了执行 定时器初始化步骤,给定一个 WindowOrWorkerGlobalScope
global、一个字符串或 Function
或 TrustedScript
handler、一个数字 timeout、一个列表 arguments、一个布尔值 repeat,以及可选地(并且仅当 repeat 为 true 时)一个数字 previousId,执行以下步骤。它们返回一个数字。
如果 global 是一个 WorkerGlobalScope
对象,则令 thisArg 为 global;否则,令 thisArg 为与 global 对应的 WindowProxy
。
如果给出了 previousId,则令 id 为 previousId;否则,令 id 为一个 实现定义的 整数,该整数大于零,并且在 global 的 setTimeout 和 setInterval ID 的映射 中尚不存在。
如果 周围代理 的 事件循环 的 当前正在运行的任务 是由此算法创建的任务,则令 嵌套级别 为 任务 的 定时器嵌套级别。否则,令 嵌套级别 为零。
任务的 定时器嵌套级别 用于对 setTimeout()
的嵌套调用以及由 setInterval()
创建的重复定时器。(或者,实际上,对于这两者的任何组合。)换句话说,它表示此算法的嵌套调用,而不是特定方法的嵌套调用。
如果 timeout 小于 0,则将 timeout 设置为 0。
如果 nesting level 大于 5,并且 timeout 小于 4,则将 timeout 设置为 4。
令 realm 为 global 的 相关领域。
令 发起脚本 为 活动脚本。
令 uniqueHandle 为 null。
令 task 为一个 任务,它运行以下子步骤
如果 id 在 global 的 setTimeout 和 setInterval ID 的映射 中不存在,则中止这些步骤。
如果 global 的 setTimeout 和 setInterval ID 的映射[id] 不等于 uniqueHandle,则中止这些步骤。
这适应了 ID 被 clearTimeout()
或 clearInterval()
调用清除,并被随后的 setTimeout()
或 setInterval()
调用重复使用的情况。
记录定时器处理程序的时间信息,给定 handler、global 的 相关设置对象 和 repeat。
如果 handler 是一个 Function
,则 调用 handler,给定 arguments 和 "report
",并且 回调 this 值 设置为 thisArg。
否则
如果未给出 previousId
如果 this 的 相关全局对象 是一个 Window
对象,则令 globalName 为 "Window
";否则为 "Worker
"。
如果 repeat 为 true,则令 methodName 为 "setInterval
";否则为 "setTimeout
"。
令 sink 为 globalName、U+0020 空格和 methodName 的连接。
将 handler 设置为使用 获取受信任类型兼容字符串 算法以及 TrustedScript
、this 的 相关全局对象、handler、sink 和 "script
" 调用的结果。
断言:handler 是一个字符串。
执行 EnsureCSPDoesNotBlockStringCompilation(realm, « », handler, handler,timer, « », handler)。如果此操作抛出异常,则捕获该异常,报告给 global,并中止这些步骤。
令 settings object 为 global 的 相关设置对象。
令 fetch options 为 默认脚本获取选项。
令 base URL 为 settings object 的 API 基础 URL。
如果 initiating script 不为 null,则
将 fetch options 设置为 脚本获取选项,其 加密 nonce 为 initiating script 的 获取选项 的 加密 nonce,完整性元数据 为空字符串,解析器元数据 为 "not-parser-inserted
",凭据模式 为 initiating script 的 获取选项 的 凭据模式,referrer 策略 为 initiating script 的 获取选项 的 referrer 策略,以及 获取优先级 为 "auto
"。
将 base URL 设置为 initiating script 的 基础 URL。
这些步骤的效果确保了由 setTimeout()
和 setInterval()
执行的字符串编译行为与由 eval()
执行的字符串编译行为等效。也就是说,模块脚本 通过 import()
进行获取在两种上下文中都将表现相同。
令 script 为给定 handler、settings object、base URL 和 fetch options 的 创建经典脚本 的结果。
运行经典脚本 script。
如果 id 在 global 的 setTimeout 和 setInterval ID 映射 中不存在,则中止这些步骤。
如果 global 的 setTimeout 和 setInterval ID 映射[id] 不等于 uniqueHandle,则中止这些步骤。
该 ID 可能已通过 handler 中作者代码调用 clearTimeout()
或 clearInterval()
而被移除。检查 uniqueHandle 是否不同,是为了考虑 ID 在被清除后,可能会被随后的 setTimeout()
或 setInterval()
调用重用的可能性。
如果 repeat 为 true,则再次执行 定时器初始化步骤,给定 global、handler、timeout、arguments、true 和 id。
否则,移除 global 的 setTimeout 和 setInterval ID 映射[id]。
将 nesting level 加 1。
将 task 的 定时器嵌套级别 设置为 nesting level。
令 completionStep 为一个算法步骤,该步骤 在给定的 global 上的 定时器任务源 上排队一个全局任务 以运行 task。
将 uniqueHandle 设置为给定 global、"setTimeout/setInterval
"、timeout 和 completionStep 的 运行超时后的步骤 的结果。
设置 global 的 setTimeout 和 setInterval ID 映射[id] 为 uniqueHandle。
返回 id。
Web IDL 中定义了参数转换(例如,对作为第一个参数传递的对象调用 toString()
方法),在调用此算法之前发生。
例如,以下相当愚蠢的代码将导致日志包含 "ONE TWO
"
var log = '' ;
function logger( s) { log += s + ' ' ; }
setTimeout({ toString: function () {
setTimeout( "logger('ONE')" , 100 );
return "logger('TWO')" ;
} }, 100 );
要连续运行多个毫秒的任务而没有任何延迟,同时仍然让浏览器恢复控制以避免饿死用户界面(并避免浏览器因占用 CPU 而终止脚本),只需在执行工作之前排队下一个定时器即可。
function doExpensiveWork() {
var done = false ;
// ...
// this part of the function takes up to five milliseconds
// set done to true if we're done
// ...
return done;
}
function rescheduleWork() {
var id = setTimeout( rescheduleWork, 0 ); // preschedule next iteration
if ( doExpensiveWork())
clearTimeout( id); // clear the timeout if we don't need it
}
function scheduleWork() {
setTimeout( rescheduleWork, 0 );
}
scheduleWork(); // queues a task to do lots of work
实现 WindowOrWorkerGlobalScope
混合体的对象具有一个 活动定时器映射,它是一个 有序映射,最初为空。此映射中的每个 键 都是一个 表示定时器的唯一内部值,每个 值 都是一个 DOMHighResTimeStamp
,表示该定时器的过期时间。
要 运行超时后的步骤,给定一个 WindowOrWorkerGlobalScope
global、一个字符串 orderingIdentifier、一个数字 milliseconds 和一组步骤 completionSteps,执行以下步骤。它们返回一个 唯一内部值。
令 timerKey 为一个新的 唯一内部值。
令 startTime 为给定 global 的 当前高分辨率时间。
并行 运行以下步骤
如果 global 是一个 Window
对象,则等待 global 的 关联的 Document
进一步处于 完全活动状态 milliseconds 毫秒(不一定连续)。
否则,global 是一个 WorkerGlobalScope
对象;等待 milliseconds 毫秒过去,并且工作线程未暂停(不一定连续)。
等待任何使用相同 global 和 orderingIdentifier、在此之前启动且 milliseconds 小于或等于此算法的 milliseconds 的此算法调用完成。
可选地,等待进一步 实现定义的 时间长度。
这旨在允许用户代理根据需要填充超时,以优化设备的功耗。例如,某些处理器具有低功耗模式,其中定时器的粒度降低;在这些平台上,用户代理可以减慢定时器速度以适应此计划,而不是要求处理器使用其相关的更高功耗的更精确模式。
执行 completionSteps。
返回 timerKey。
运行超时后的步骤 旨在供其他规范使用,这些规范希望以类似于 setTimeout()
的方式在开发者提供的超时后执行开发者提供的代码。(但是,请注意,它没有 setTimeout()
的嵌套和钳位行为。)此类规范可以选择一个 orderingIdentifier 以确保其规范的超时内的顺序,同时不限制相对于其他规范的超时的顺序。
所有当前引擎都支持。
queueMicrotask(callback)
方法必须 排队一个微任务 以 调用 callback,并传入 « » 和 "report
"。
queueMicrotask()
方法允许作者在 微任务队列 上安排回调。这允许他们的代码在 JavaScript 执行上下文栈 下次为空时运行,这发生在所有当前正在执行的同步 JavaScript 运行完成之后。这不会将控制权交还给 事件循环,例如,使用 setTimeout(f, 0)
时的情况。
作者应该意识到,安排大量微任务与运行大量同步代码具有相同的性能缺点。两者都会阻止浏览器执行自己的工作,例如渲染。在许多情况下,requestAnimationFrame()
或 requestIdleCallback()
是更好的选择。特别是,如果目标是在下一个渲染周期之前运行代码,那么这就是 requestAnimationFrame()
的用途。
从以下示例可以看出,理解 queueMicrotask()
的最佳方式是将其视为一种重新排列同步代码的机制,有效地将排队的代码放置在当前正在执行的同步 JavaScript 运行完成之后。
使用queueMicrotask()
最常见的原因是创建一致的排序,即使在同步可用信息的情况下,也不会引入不必要的延迟。
例如,考虑一个自定义元素触发load
事件,该事件还维护一个先前加载数据的内部缓存。一个简单的实现可能如下所示
MyElement. prototype. loadData = function ( url) {
if ( this . _cache[ url]) {
this . _setData( this . _cache[ url]);
this . dispatchEvent( new Event( "load" ));
} else {
fetch( url). then( res => res. arrayBuffer()). then( data => {
this . _cache[ url] = data;
this . _setData( data);
this . dispatchEvent( new Event( "load" ));
});
}
};
然而,这个简单的实现存在问题,因为它会导致用户体验不一致的行为。例如,如下代码
element. addEventListener( "load" , () => console. log( "loaded" ));
console. log( "1" );
element. loadData();
console. log( "2" );
有时会记录“1, 2, loaded”(如果需要获取数据),有时会记录“1, loaded, 2”(如果数据已缓存)。类似地,在调用loadData()
之后,元素上是否设置数据将是不一致的。
为了获得一致的排序,可以使用queueMicrotask()
MyElement. prototype. loadData = function ( url) {
if ( this . _cache[ url]) {
queueMicrotask(() => {
this . _setData( this . _cache[ url]);
this . dispatchEvent( new Event( "load" ));
});
} else {
fetch( url). then( res => res. arrayBuffer()). then( data => {
this . _cache[ url] = data;
this . _setData( data);
this . dispatchEvent( new Event( "load" ));
});
}
};
通过实质上重新安排排队的代码,使其位于JavaScript执行上下文栈清空之后,这确保了元素状态的一致排序和更新。
另一个有趣的queueMicrotask()
用法是允许多个调用者进行不协调的“批量”处理。例如,考虑一个库函数,它希望尽快将数据发送到某个地方,但如果很容易避免,则不想发出多个网络请求。平衡这一点的一种方法如下所示
const queuedToSend = [];
function sendData( data) {
queuedToSend. push( data);
if ( queuedToSend. length === 1 ) {
queueMicrotask(() => {
const stringToSend = JSON. stringify( queuedToSend);
queuedToSend. length = 0 ;
fetch( "/endpoint" , stringToSend);
});
}
}
通过这种架构,在当前正在执行的同步JavaScript中对sendData()
的多次后续调用将被批量组合成一个fetch()
调用,但没有中间的事件循环任务抢占获取操作(就像使用setTimeout()
的类似代码那样会发生的情况)。
window.alert(message)
所有当前引擎都支持。
显示带有给定消息的模态警报,并等待用户将其关闭。
result = window.confirm(message)
所有当前引擎都支持。
显示带有给定消息的模态“确定/取消”提示,等待用户将其关闭,如果用户点击“确定”则返回true,如果用户点击“取消”则返回false。
result = window.prompt(message [, default])
所有当前引擎都支持。
显示带有给定消息的模态文本控件提示,等待用户将其关闭,并返回用户输入的值。如果用户取消提示,则返回null。如果存在第二个参数,则使用给定值作为默认值。
依赖于任务或微任务的逻辑,例如媒体元素加载其媒体数据,在调用这些方法时会暂停。
The alert()
和 alert(message)
方法步骤如下
如果我们无法显示简单对话框,则返回。
如果方法未带参数调用,则令message为空字符串;否则,令message为方法的第一个参数。
将message设置为给定message的结果规范化换行符。
将message设置为可选截断message的结果。
将message显示给用户,将U+000A LF视为换行符。
使用this、"alert
"和message调用WebDriver BiDi用户提示已打开。
可选地,在等待用户确认消息时暂停。
使用this和true调用WebDriver BiDi用户提示已关闭。
出于历史原因,此方法使用两个重载来定义,而不是使用可选参数。这带来的实际影响是alert(undefined)
被视为alert("undefined")
,但alert()
被视为alert("")
。
The confirm(message)
方法步骤如下
如果我们无法显示简单对话框,则返回false。
将message设置为给定message的结果规范化换行符。
将message设置为可选截断message的结果。
将message显示给用户,将U+000A LF视为换行符,并要求用户以肯定或否定响应。
使用this、"confirm
"和message调用WebDriver BiDi用户提示已打开。
直到用户肯定或否定响应时暂停。
使用this,如果用户肯定响应则为true,否则为false,调用WebDriver BiDi用户提示已关闭。
如果用户肯定响应,则返回true;否则,用户否定响应:返回false。
The prompt(message, default)
方法步骤如下
如果我们无法显示简单对话框,则返回null。
将message设置为给定message的结果规范化换行符。
将message设置为可选截断message的结果。
将default设置为可选截断default的结果。
将message显示给用户,将U+000A LF视为换行符,并要求用户以字符串值或中止响应。响应必须默认为default给出的值。
使用this、"prompt
"、message和default调用WebDriver BiDi用户提示已打开。
在等待用户响应时暂停。
如果用户中止,则令result为null,否则为用户响应的字符串。
使用this,如果result为null则为false,否则为true,以及result调用WebDriver BiDi用户提示已关闭。
返回result。
要可选截断简单对话框字符串s,则返回s本身或从s派生的某个较短的字符串。用户代理不应提供用于显示s省略部分的UI,因为这使得滥用者很容易创建“重要安全警报!点击“显示更多”以查看完整详细信息!”形式的对话框。
例如,用户代理可能只想显示消息的前100个字符。或者,用户代理可能会用“…”替换字符串的中间部分。这些类型的修改对于限制不自然地大、看起来可信的系统对话框的滥用潜力很有用。
当以下算法返回true时,我们无法显示简单对话框。
如果window的关联的Document
的活动沙箱标志集具有沙箱模态标志,则返回true。
可选返回true。(例如,用户代理可能会让用户选择忽略所有模态对话框,因此无论何时调用该方法都会在此步骤中止。)
返回false。
所有当前引擎都支持。
window.print()
提示用户打印页面。
The print()
方法的步骤如下:
令 document 为 this 的 关联的 Document
。
如果 document 不是 完全激活 的,则返回。
如果 document 的 卸载计数器 大于 0,则返回。
如果 document 已 准备好执行加载后任务,则对 document 运行 打印步骤。
否则,设置 document 的 加载时打印 标志。
用户代理还应在用户请求获得 物理形式(例如打印副本) 或物理形式的表示(例如 PDF 副本)的机会时运行 打印步骤。
对 Document
document 的 打印步骤 如下:
用户代理可能会向用户显示消息或返回(或两者都执行)。
例如,自助服务终端浏览器可以静默忽略对 print()
方法的任何调用。
例如,移动设备上的浏览器可以检测到附近没有打印机,并在继续提供“保存为 PDF”选项之前显示一条消息。
如果 document 的 活动沙箱标志集 设置了 沙箱模式对话框标志,则返回。
如果打印对话框被 Document
的沙箱阻止,则不会触发 beforeprint
或 afterprint
事件。
用户代理必须在 document 的 相关全局对象 以及其中的任何 子可导航对象 上 触发一个名为 beforeprint
的事件。
仅在子元素中触发在这里似乎不正确,并且某些任务可能需要排队。请参阅 问题 #5096。
beforeprint
事件可用于注释打印副本,例如添加文档打印时间。
用户代理应为用户提供获得 物理形式(或物理形式的表示) 的机会。用户代理可能会等待用户接受或拒绝后再返回;如果这样做,用户代理必须在方法等待时 暂停。即使用户代理此时没有等待,如果并且当它最终创建备用表单时,用户代理也必须使用相关文档在此算法中的状态。
用户代理必须在 document 的 相关全局对象 以及其中的任何 子可导航对象 上 触发一个名为 afterprint
的事件。
仅在子元素中触发在这里似乎不正确,并且某些任务可能需要排队。请参阅 问题 #5096。
afterprint
事件可用于恢复在较早事件中添加的注释,以及显示打印后 UI。例如,如果页面正在引导用户完成申请住房贷款的步骤,则脚本可以在打印表单或其他内容后自动进入下一步。