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

在 async 函数中加载有依赖关系的动态脚本,核心是**确保脚本按顺序执行、避免竞态、并正确暴露全局变量或模块接口**。不能简单用 await import()(它不适用于传统 script 标签加载的库),也不能只靠 Promise.all(会破坏依赖顺序)。
用 Promise 封装动态 <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 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
async function loadScriptWithCheck(src, globalName, timeout = 5000) {
await loadScript(src);
const start = Date.now();
while (!window[globalName] && Date.now() - start < timeout) {
await new Promise(r => 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);
}调用 await loadWithDeps('datatables') 即可自动先加载 jQuery,再加载 DataTables。

















