如何检测动态注入的script脚本是否已完成执行
动态注入script脚本执行完成检测方案
场景1:仅注入同步执行的内联脚本(你当前的实现场景)
你当前的代码中没有给script添加async/defer属性,动态插入的无src属性的内联脚本,会在appendChild调用时同步执行,脚本内所有同步代码执行完成后,才会继续执行appendChild之后的代码。也就是说你现有写法里的someCode()本来就已经是在注入脚本运行完成后才触发的,可以直接正常使用。
验证示例:
const InjectScript = (scriptContent) => { const script = document.createElement("script"); script.type = "text/javascript"; script.text = scriptContent; document.head.appendChild(script); // 此处已经可以正常访问注入脚本内定义的变量和方法 console.log(window.testVal) // 输出123 }; InjectScript(`window.testVal = 123`)
场景2:注入脚本包含异步逻辑,或需要兼容外部src脚本加载
如果注入的脚本里有异步操作(比如接口请求、定时器、async函数),或者后续需要改成加载外部js文件,可以用以下两种方案实现精准监听:
方案1:自定义事件回调(可灵活控制执行时机)
如果可以修改注入的脚本内容,在脚本所有需要执行的逻辑结束后触发自定义事件,外层监听该事件即可:
const InjectScript = (scriptContent, callback) => { const eventName = 'customScriptExecuted' // 注册一次性事件监听 window.addEventListener(eventName, () => { callback?.() }, { once: true }) const script = document.createElement("script"); script.type = "text/javascript"; // 同步逻辑可以直接在脚本末尾拼接事件触发代码,异步逻辑可以在异步回调内主动触发 script.text = scriptContent; document.head.appendChild(script); }; // 调用示例 InjectScript(` setTimeout(() => { window.testVal = 123 // 异步逻辑执行完成后主动触发事件 window.dispatchEvent(new CustomEvent('customScriptExecuted')) }, 1000) `, () => { console.log('脚本逻辑全部执行完成', window.testVal) // 1秒后输出123 })
方案2:通用load事件监听(兼容内联/外部脚本)
如果不需要控制异步逻辑结束时机,只需要监听脚本本身同步代码执行完成,或是加载外部src脚本,可以监听script的load和error事件,用Promise封装更易用:
const InjectScript = (scriptContent, isExternal = false) => { return new Promise((resolve, reject) => { const script = document.createElement("script"); script.type = "text/javascript"; if (isExternal) { script.src = scriptContent } else { script.text = scriptContent } // 执行/加载成功回调 script.onload = () => resolve() // 执行/加载失败回调 script.onerror = (err) => reject(err) document.head.appendChild(script); }) }; // 调用示例:注入内联脚本 InjectScript(`window.testVal = 123`).then(() => { console.log('内联脚本同步代码执行完成', window.testVal) }).catch(err => { console.error('脚本执行出错', err) }) // 调用示例:注入外部脚本 InjectScript('https://example.com/test.js', true).then(() => { console.log('外部脚本加载执行完成') })
注意:内联脚本的load事件在Chrome、Firefox、Safari 10+、Edge等主流浏览器都可以正常触发,仅需要兼容IE9及以下极老旧浏览器时才需要额外做兼容处理。
内容的提问来源于stack exchange,提问作者Masksway
相关产品推荐
相关产品推荐

