定时器不能替代依赖就绪判断,必须通过<script>的onload事件、Promise封装或专用加载器来确保脚本真正就绪;轮询仅作兜底且需设超时与退出条件;复杂依赖链应交由轻量加载器统一管理。

定时器本身不管理依赖,它只是按时间触发回调——把定时器当作“依赖管理工具”用,容易引发执行错乱、资源竞争或重复加载。真正可靠的依赖管理,得靠加载机制本身(如动态 <script> 插入 + onload 事件、Promise 封装、或专用加载器),而不是靠 setTimeout 或 setInterval 去“等”脚本就绪。
定时器不能替代依赖就绪判断
常见误区是写这样的代码:
loadJS("lib.js");<br>setTimeout(() => {<br> // 假设 lib.js 已加载,直接调用<br> initPlugin();<br>}, 500);这不可靠:网络波动、缓存失效、脚本执行慢,都可能导致 500ms 内 lib.js 还没执行完,initPlugin 就报 is not defined。浏览器不保证脚本下载完成即执行,更不保证执行完毕——必须监听真实就绪信号。
- 用
<script>的onload或onerror事件捕获加载完成 - 用 Promise 封装加载过程,让后续逻辑
await它 - 用
loadJS(src, callback)这类加载器的回调机制,而非自己计时
定时器适合做兜底或轮询检查,不是主流程
当无法监听确切就绪事件(比如第三方 SDK 只提供全局变量名,且无加载钩子),可结合定时器做安全轮询,但需加退出条件和防抖:
立即学习“Java免费学习笔记(深入)”;
function waitForGlobal(name, timeout = 3000) {<br> return new Promise((resolve, reject) => {<br> const start = Date.now();<br> const check = () => {<br> if (window[name]) return resolve(window[name]);<br> if (Date.now() - start > timeout) return reject(new Error(`${name} 超时未就绪`));<br> setTimeout(check, 50); // 每 50ms 查一次,避免频繁轮询<br> };<br> check();<br> });<br>}<br><br>// 使用<br>waitForGlobal("jQuery").then($ => {<br> console.log("jQuery 已可用", $.fn.jquery);<br>}).catch(err => console.error(err));- 轮询间隔不宜过短(
- 必须设超时上限,防止无限等待
- 检测目标应为可判定的状态(如全局变量、DOM 元素、函数存在性),而非“时间到了”
避免在定时器回调里做加载决策
不要这样写:
setInterval(() => {<br> if (!window.myLib) {<br> loadJS("my-lib.js");<br> }<br>, 1000);问题明显:可能重复插入同一脚本;若加载失败,会无限重试;没有错误反馈路径。正确做法是把加载逻辑与状态检查分离:
- 一次性触发加载,用回调或 Promise 处理成功/失败
- 加载失败后记录状态,避免反复尝试(例如设置
window.myLibLoadFailed = true) - 需要重试时,显式调用带退避策略的函数,而非固定间隔轮询
复杂依赖链建议交给专用加载器
多个脚本有明确先后关系(如 A → B → C),靠定时器协调极难维护。推荐使用轻量加载器统一管理:
// LoadJS 示例:true 表示有序执行<br>loadJS("a.js", true);<br>loadJS("b.js", true);<br>loadJS("c.js", () => {<br> console.log("A→B→C 全部就绪");<br> runApp();<br>});- 加载器内部用
onload串起执行顺序,不依赖时间猜测 - 支持失败回调,便于监控和降级
- 体积小(如 LoadJS 仅 961 字节),无额外运行时负担


















