如何用JavaScript/jQuery在首个脚本加载失败时加载备用脚本?
问题根源
你的代码之所以会持续请求dev.js并报错,核心原因是live.js的自动刷新特性:当live.js加载后,它会监测文件变化并触发页面刷新;页面刷新后你的脚本会重新执行,再次尝试请求dev.js,失败后又加载live.js,形成无限循环。
优化解决方案
方案1:原生JavaScript实现(无jQuery依赖)
用原生JS更灵活,同时加入会话标记打破循环:
// 标记是否已尝试加载dev.js,避免页面刷新后重复请求 if (!sessionStorage.getItem('devJsAttempted')) { sessionStorage.setItem('devJsAttempted', 'true'); const devScript = document.createElement('script'); devScript.src = 'http://localhost:3000/dev.js'; devScript.onload = () => console.log('dev.js加载成功'); devScript.onerror = () => { console.log('dev.js加载失败,切换加载live.js'); const liveScript = document.createElement('script'); liveScript.src = 'https://cdn.jsdelivr.net/live.js'; liveScript.onload = () => console.log('live.js加载成功'); liveScript.onerror = () => console.log('live.js加载失败'); document.head.appendChild(liveScript); }; document.head.appendChild(devScript); }
方案优势:
- 用
sessionStorage记录尝试状态,会话期间页面刷新不会重复请求dev.js,彻底打破循环; - 原生API无额外依赖,性能更优,避免jQuery封装可能带来的隐性问题。
方案2:改进jQuery版本(保留原有技术栈)
如果必须用jQuery,同样加入会话标记即可:
if (!sessionStorage.getItem('devJsAttempted')) { sessionStorage.setItem('devJsAttempted', 'true'); $.getScript("http://localhost:3000/dev.js") .done(() => console.log('dev.js加载成功')) .fail(() => { console.log('dev.js加载失败,尝试加载live.js'); $.getScript("https://cdn.jsdelivr.net/live.js") .done(() => console.log('live.js加载成功')) .fail(() => console.log('live.js加载失败')); }); }
进阶优化:环境判断直接分流
如果线上环境永远不需要加载dev.js,可以通过域名判断环境,从根源上避免无效请求:
// 判断是否为本地开发环境 if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') { // 本地优先加载dev.js,失败再 fallback 到live.js $.getScript("http://localhost:3000/dev.js") .fail(() => $.getScript("https://cdn.jsdelivr.net/live.js")); } else { // 线上环境直接加载live.js $.getScript("https://cdn.jsdelivr.net/live.js"); }
这种方式完全避免了线上环境请求dev.js的行为,自然不会出现循环报错。
内容的提问来源于stack exchange,提问作者Imran Subhani
相关产品推荐
相关产品推荐

