动态加载外部JS文件后如何正确获取全局类实例及调用类方法
动态加载外部JS文件后如何正确获取全局类实例及调用类方法
嘿,你的问题核心其实是没搞懂动态加载脚本的异步特性——你写的同步代码会比Promise的then回调先执行,这时候脚本还没加载完,类和实例自然都不存在,所以才会报错。我来给你拆解问题并给出具体的解决办法:
先说说你遇到的两个错误原因
为什么
var appi = new Application()会报错?
因为injectScript是异步执行的,它返回的Promise会在脚本加载完成后才触发then,但你写的var appi = new Application()是同步代码,会在脚本开始加载但还没加载完成时就运行,这时候Application类根本还没被定义,自然会提示“类未定义”。为什么后面的
app.showText()会报错?
同样的道理,这个同步代码会比then里的app = new Application()先执行,此时app还是你一开始声明的undefined,当然没有showText方法。
解决方案一:用async/await让逻辑更清晰(推荐)
把所有依赖加载后代码放到async函数里,用await等待脚本加载完成,这样代码逻辑就像同步一样,但实际是异步执行的:
/* 加载外部JS的函数保持不变 */ function injectScript(src) { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = src; script.addEventListener('load', resolve); script.addEventListener('error', e => reject(e.error)); document.head.appendChild(script); }); } /* 用async函数封装初始化逻辑 */ async function initApplication() { try { // 等待脚本加载完成,这一步完成后Application类才会被定义 await injectScript('application.js'); // 实例化并挂载到window上,让全局都能访问 window.app = new Application(); // 现在可以正常调用方法了 app.showText(); // 这里也能正常实例化新的对象 const appi = new Application(); appi.showText(); } catch (error) { console.error('加载脚本时出错:', error); } } // 启动初始化 initApplication();
解决方案二:如果需要在其他代码块调用,用自定义事件通知
如果你的代码分散在不同地方,不想都塞进一个async函数,可以用自定义事件来通知“App已经准备好”,其他地方监听这个事件再执行代码:
async function initApplication() { try { await injectScript('application.js'); window.app = new Application(); // 触发自定义事件,告诉其他代码App已就绪 document.dispatchEvent(new CustomEvent('appReady')); } catch (error) { console.error(error); } } initApplication(); // 在需要调用的地方监听事件 document.addEventListener('appReady', () => { // 现在app已经存在,可以正常调用方法 app.showText(); // 也能正常实例化Application类 const appi = new Application(); appi.showText(); });
关键要点总结
- 动态加载脚本是异步操作,所有依赖这个脚本的代码必须等待加载完成后才能执行,不能直接写在加载代码的后面(同步执行)。
- 如果需要全局访问实例,把实例挂载到
window对象上是最简单的方式(当然你也可以用模块化方案,但你说不想用服务器,所以全局挂载最直接)。 - 跨代码块的依赖调用,用自定义事件或者Promise链式调用都是可靠的方式,核心就是等待加载完成的信号再执行后续代码。
备注:内容来源于stack exchange,提问作者Orbit
相关产品推荐
相关产品推荐

