在async函数中加载有依赖关系的动态脚本,需用promise封装script加载、按依赖顺序依次await、轮询检查全局变量就绪,并可封装为支持拓扑排序的依赖加载器。

在 async 函数中加载有依赖关系的动态脚本,核心是**确保脚本按顺序执行、避免竞态、并正确暴露全局变量或模块接口**。不能简单用 await import()(它不适用于传统 script 标签加载的库),也不能只靠 Promise.all(会破坏依赖顺序)。
用 Promise 封装动态 <script></script> 加载
每个脚本加载应返回一个可 await 的 Promise,成功时 resolve,失败时 reject:
function loadScript(src) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = src;
script.onload = () => resolve();
script.onerror = () => reject(new Error(`Failed to load script: ${src}`));
document.head.appendChild(script);
});
}按依赖顺序依次 await
若 B 依赖 A(例如 jQuery → jQuery 插件),必须等 A 完全加载并初始化后再加载 B:
- 不要写
await Promise.all([loadScript('a.js'), loadScript('b.js')])—— 并发加载会出错 - 要写
await loadScript('a.js'); await loadScript('b.js'); - 如果依赖链更长(A → B → C),就连续 await,自然形成串行执行流
等待全局变量/对象就绪(防“未定义”错误)
有些库(如旧版 Lodash 或第三方插件)只挂载到 window,但 onload 触发时变量未必已赋值完成(尤其压缩混淆后)。可加轮询兜底:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
async function loadScriptWithCheck(src, globalName, timeout = 5000) {
await loadScript(src);
const start = Date.now();
while (!window[globalName] && Date.now() - start setTimeout(r, 10));
}
if (!window[globalName]) throw new Error(`${globalName} not available after loading ${src}`);
}使用示例:await loadScriptWithCheck('https://cdn.jsdelivr.net/npm/jquery@3.7/dist/jquery.min.js', 'jQuery');
封装成可复用的依赖加载器
把脚本路径和依赖声明为配置,自动拓扑排序(适合中大型项目):
const scriptDeps = {
'jquery': { src: 'https://cdn.jsdelivr.net/npm/jquery@3.7/dist/jquery.min.js' },
'datatables': {
src: 'https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js',
dependsOn: ['jquery']
}
};
<p>async function loadWithDeps(target) {
const deps = scriptDeps[target].dependsOn || [];
for (const dep of deps) await loadWithDeps(dep);
await loadScript(scriptDeps[target].src);
}</p>调用 await loadWithDeps('datatables') 即可自动先加载 jQuery,再加载 DataTables。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










