You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

浏览器环境下如何在指定脚本加载完成后调用其函数(仅关注目标脚本)

问题描述

我的HTML中有两个script标签:

<script src="first.js"></script> 
<script src="second.js"></script>

其中first.js是一个大型库文件,加载完成后会提供funcFromFirstJs函数。我希望在该函数就绪时调用它,但有时first.js还未加载完成,second.js就已开始执行。

目前我采用递归检查的方式实现:

// second.js
function callIfReady() {
  if (typeof funcFromFirstJs === 'function') {
    funcFromFirstJs();
  } else {
    // 等待一段时间后再次调用callIfReady()
  }
}

请问是否有更优的实现方式?我了解window的load事件(会在包括图片在内的所有资源加载完成后触发),也了解document的DOMContentLoaded事件(在标签加载完成后触发,但可能早于内容加载完毕)。由于first.js是库文件,我不想在其末尾添加自定义代码,仅希望等待first.js完全加载完成后,再执行second.js中的对应代码,完全不关心图片或其他脚本的加载进度,因此不想使用window的load事件。


更优实现方案

1. 监听目标脚本的load事件

这是最精准匹配需求的方案,直接追踪first.js的加载状态:

  • 如果能修改HTML中的script标签,直接添加onload事件:
<script src="first.js" onload="funcFromFirstJs()"></script>
<script src="second.js"></script>
  • 若无法修改HTML,可在second.js中获取目标脚本标签并绑定事件:
// second.js
const firstScript = document.querySelector('script[src="first.js"]');

// 先检查脚本是否已加载完成
if (firstScript.readyState === 'complete' || firstScript.readyState === 'loaded') {
  funcFromFirstJs();
} else {
  firstScript.addEventListener('load', () => {
    funcFromFirstJs();
  });
}

这种方式只关注first.js的加载状态,完全不受其他资源影响。

2. 用MutationObserver替代递归轮询

比起定时器递归检查,MutationObserver是更高效的监听方式,全局变量一就绪就触发执行:

// second.js
const observer = new MutationObserver(() => {
  if (typeof funcFromFirstJs === 'function') {
    funcFromFirstJs();
    observer.disconnect(); // 执行完成后停止监听
  }
});

observer.observe(window, {
  propertyFilter: ['funcFromFirstJs'] // 仅监听目标变量的变化
});

// 先做一次即时检查,避免脚本已提前加载完成的情况
if (typeof funcFromFirstJs === 'function') {
  funcFromFirstJs();
  observer.disconnect();
}

没有定时器的延迟和多余性能开销,比递归轮询更优雅。

3. 动态加载脚本(可选方案)

如果允许调整脚本加载逻辑,可以在second.js中主动控制first.js的加载顺序:

// second.js
function loadScript(src, callback) {
  const script = document.createElement('script');
  script.src = src;
  script.onload = callback;
  // 可添加重复加载判断,避免重复插入脚本
  if (!document.querySelector(`script[src="${src}"]`)) {
    document.body.appendChild(script);
  }
}

// 加载first.js完成后执行目标函数
loadScript('first.js', () => {
  funcFromFirstJs();
});

这种方式彻底掌控脚本加载顺序,但需要注意避免重复加载first.js。

内容的提问来源于stack exchange,提问作者Morris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 20:17:40