追加含JS资源的HTML时的JS加载机制困惑
动态追加跨域脚本时的加载执行延迟问题解析
极简答案
- 浏览器加载跨域外部脚本时默认是异步的,不会阻塞后续inline脚本的执行;而同域脚本会被浏览器优化为同步加载/执行,这就是你看到差异的核心原因。
- 你注入的inline脚本会立即运行,此时跨域的JW Player脚本还在后台下载,所以
jwplayer是undefined;5秒后脚本下载完成并执行,函数自然就存在了。
深度解析:浏览器脚本加载机制
当你通过append()这类方法注入包含<script src="跨域URL">的HTML块时,浏览器的处理逻辑是这样的:
- 异步请求启动:跨域外部脚本的加载请求会被浏览器放到后台处理,不会暂停当前的JS执行流程——也就是说,后面的inline脚本会直接跑起来,完全不等跨域脚本下载完。
- 执行队列排队:只有当跨域脚本下载完成后,它才会被加入到JS执行队列里,等当前所有正在运行的代码(包括你的inline脚本)都执行完,才会轮到它执行。这就导致你在inline脚本里访问
jwplayer时,它还没被定义。
同域脚本无延迟的原因
对于同域的外部脚本,浏览器会有更激进的优化策略:
- 浏览器可能会提前预加载同域资源,或者在解析注入的HTML时,把同域脚本的加载标记为同步模式——因为同域资源的安全性可控,浏览器可以更严格地保证加载顺序,所以脚本会在你的inline脚本执行前就完成加载并执行,自然能立即访问到
jwplayer。
靠谱的解决方案
如果想在脚本加载完成后立刻执行依赖代码,别用HTML字符串注入的方式,手动创建脚本元素并监听load事件更稳妥:
const jwScript = document.createElement('script'); jwScript.src = 'https://cdn.jwplayer.com/libraries/gHnukrbe.js'; // 脚本加载完成后再执行代码 jwScript.onload = function() { $("#output").append("<p>is jwplayer declared? " + typeof jwplayer + "</p>"); }; // 添加到页面中启动加载 document.getElementById('output').appendChild(jwScript);
这种方式能精准控制代码执行时机,完全避免延迟问题。
内容的提问来源于stack exchange,提问作者Augusto
相关产品推荐
相关产品推荐

