ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

core-js 中的 setImmediate / clearImmediate:Web 定时调度 API 的跨运行时 Polyfill 实现解析

core-js 中的 setImmediate / clearImmediate:Web 定时调度 API 的跨运行时 Polyfill 实现解析 core-js 中的 setImmediate / clearImmediateWeb 定时调度 API 的跨运行时 Polyfill 实现解析【免费下载链接】core-jsStandard Library项目地址: https://gitcode.com/GitHub_Trending/co/core-jssetImmediate与clearImmediate是源自 W3C 的 Web 标准定时调度 API前者将回调任务安排在当前操作完成后、下一次事件循环轮询之前以最小延迟执行后者用于取消尚未执行的任务。本文以 docs/web/docs/features/web-standards/setimmediate.md 为骨架结合 core-js 仓库中web.immediate模块及其底层task实现的源码完整讲解这两个 API 的签名、按需引入方式、运行示例以及它们在 Node.js、浏览器、Web Worker、旧版 IE 等不同运行时下的降级调度原理与已知兼容性修复。setImmediate / clearImmediate 是什么在 core-js 的模块划分中setImmediate与clearImmediate属于web standardsWeb 标准类别对应模块名web.immediate实现的规范来源是 W3C 的 setImmediate 草案相关链接见原文档。与setTimeout(fn, 0)相比setImmediate的任务优先级更高它表示在当前阶段工作完成后立即执行常用于需要把昂贵操作拆解为若干小任务、避免阻塞主线程的场景。setImmediate与setTimeout一样属于宏任务macrotask调度体系但它不依赖毫秒级延迟因此可以更早地被调度。值得注意的一个实现细节是在 core-js 的web.immediate入口模块源码中可以看到一条 TODO 注释——TODO: Remove this module fromcore-js4since its split to modules listed below即该聚合模块仅是为了兼容历史入口实际功能已拆分为web.set-immediate与web.clear-immediate两个独立模块。API 签名与语义原文档给出的类型签名如下function setImmediate(callback: any, ...args: Arraymixed): number; function clearImmediate(id: number): void;语义要点setImmediate(callback, ...args)在最短延迟内执行callback...args作为额外参数透传给回调返回值是本次调度的唯一标识id数值类型。clearImmediate(id)根据setImmediate返回的id取消尚未执行的任务若任务已执行完毕或id不存在则静默无操作。结合底层实现 packages/core-js/internals/task.js 可以印证内部使用递增计数器counter生成id把回调与参数打包成queue[counter]闭包存入队列clear则是简单地delete queue[id]——因此重复清除、清除不存在的 id 都不会报错。同时setImmediate内部会通过validateArgumentsLength(arguments.length, 1)强制要求至少传入 1 个参数否则抛出异常。安装与按需入口Entry Points原文档给出了两个 API 的按需引入路径core-js(-pure)/stable|actual|full/set-immediate core-js(-pure)/stable|actual|full/clear-immediate即setImmediate与clearImmediate支持通过stable、actual、full三个命名空间分别按需引入。以全局版本为例对应到仓库中的入口文件包括packages/core-js/stable/set-immediate.jsrequire(../modules/web.immediate)后导出path.setImmediatepackages/core-js/stable/clear-immediate.js同样加载web.immediate模块后导出path.clearImmediatepackages/core-js/actual/set-immediate.js 与full版本则逐级继承自stable入口保持命名空间之间的包含关系。实际使用时的引入方式// 仅补丁 setImmediate / clearImmediate按需最小引入 import core-js/stable/set-immediate; import core-js/stable/clear-immediate; // 或者使用 actual / full 命名空间 import core-js/actual/set-immediate; import core-js/full/clear-immediate;关于三个命名空间的选择docs/web/docs/usage.md 中的说明同样适用stable仅包含稳定的 ES 特性与 Web 标准actual额外包含 Stage 3 提案官方推荐日常使用full则包含所有特性含早期提案。如果只想整体引入而不做按需裁剪也可以直接import core-js/stable或import core-js/full。需要注意usage.md中的两条警告同样适用modules路径属于内部 API不保证注入所有依赖仅建议用于自定义构建按需入口应尽量在应用入口文件顶部统一加载避免与其他扩展原生对象的库产生冲突。运行示例原文档给出的示例完整继承了 setImmediate 的两个核心行为——正常调度与提前取消setImmediate((arg1, arg2) { console.log(arg1, arg2); // Message will be displayed with minimum delay }, Message will be displayed, with minimum delay); clearImmediate(setImmediate(() { console.log(Message will not be displayed); }));执行结果分析第一段setImmediate把两个字符串参数透传给回调回调在最短延迟后执行控制台打印Message will be displayed with minimum delay第二段setImmediate返回的id立刻被传给clearImmediate任务在被调度执行前即被移除因此回调永远不会触发控制台不输出任何内容。对第二段行为的底层佐证同样在 task.js调度器最终执行的是run(id)而run会先检查hasOwn(queue, id)再取出并删除回调一旦id已被clear删除run直接返回回调不会执行。底层实现task 调度器的多运行时降级链setImmediate的全局暴露由 packages/core-js/modules/web.set-immediate.js 完成它通过internals/task的set获取调度器再经schedulersFix包装后挂到全局forced条件为globalThis.setImmediate ! setImmediate即仅在运行时缺少原生实现或原生实现与 polyfill 不一致时才覆盖。clearImmediate模块 packages/core-js/modules/web.clear-immediate.js 的处理方式与之完全对称。真正的跨平台调度逻辑集中在 packages/core-js/internals/task.js。当运行时没有原生setImmediate/clearImmediate时core-js 按以下优先级选择defer延迟执行器Node.js 0.8 及更早版本使用process.nextTick(runner(id))调度SphereJS 游戏引擎存在Dispatch.now时使用Dispatch.now(runner(id))支持 MessageChannel 的浏览器含 Web Worker但排除 iOS创建MessageChannel通过port1.onmessage监听事件、port2.postMessage触发调度见 task.js。排除 iOS 的原因对应仓库 issue 记录见源码注释支持 postMessage 的浏览器排除 Web Worker条件为存在addEventListener、postMessage可调用、无importScripts即非 worker、location.protocol ! file:且 postMessage 的异步行为测试通过此时通过globalThis.postMessage(String(id), location.protocol // location.host)广播消息再统一监听message事件执行见 task.js。同时源码也对location的访问做了容错Deno 在无--location标志时会抛ReferenceErrorIE8 及更早版本利用script元素的onreadystatechange事件动态向htmldocumentElement插入 script 标签触发调度执行后立即移除节点兜底方案其余旧环境一律退化为setTimeout(runner(id), 0)。这条降级链保证了 polyfill 在绝大多数 JS 运行时上都能以尽量接近原生 setImmediate 语义的方式工作且由于调度实现不依赖毫秒延迟能获得比setTimeout(fn, 0)更早的执行时机。已知兼容性修复schedulers-fix在 packages/core-js/modules/web.set-immediate.js 中可以看到一个特殊处理var setImmediate globalThis.setImmediate ? schedulersFix(setTask, false) : setTask;也就是说当运行时存在原生setImmediate时core-js 仍会对其做一次包装而不是直接使用。原因在 packages/core-js/internals/schedulers-fix.js 中说明IE9- 与 Bun 0.3.0- 的setTimeout/setInterval/setImmediate存在附加参数不被正确透传的缺陷关联 Bun issue 见源码注释。schedulersFix(scheduler, hasTimeArg)在检测到WRAP条件UA 匹配MSIE x.或 Bun 版本 0.3.0时会生成一个包装函数将多出的参数切片后闭包绑定进回调再调用原始调度器hasTimeArg参数用于区分setImmediate无 time 参数firstParamIndex 1与setTimeout/setInterval有 time 参数firstParamIndex 2。这也解释了为什么 web.set-immediate.js 中调用时传入false。在非WRAP环境下现代浏览器、新版本 Node.js/BunschedulersFix直接原样返回原生调度器不引入任何额外开销。测试与验证core-js 为web.immediate提供了对应的单元测试位于 tests/unit-global/web.set-immediate.js与其它web.*模块如queue-microtask、set-timeout、set-interval并列覆盖了回调执行、参数透传以及clearImmediate取消调度等核心行为。读者在本地运行测试时可参照 tests/unit-global/ 目录下其它测试的组织方式将测试文件按项目既有测试运行流程执行。小结setImmediate/clearImmediate是 core-js Web 标准补丁中机制相对简单、但跨平台实现相当讲究的一对 API对外只需记住注册回调返回 id、凭 id 取消任务的签名与core-js(-pure)/stable|actual|full/{set,clear}-immediate的按需入口对内则是一张覆盖 Node.js、现代浏览器、Web Worker、旧 IE 的多级调度降级链外加对 IE9-/Bun 早期版本附加参数缺陷的定向修复。理解这条实现链有助于在依赖 core-js 的项目中准确预期setImmediate在不同运行环境下的调度行为与边界情况。【免费下载链接】core-jsStandard Library项目地址: https://gitcode.com/GitHub_Trending/co/core-js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表