.then()中传入的函数未执行?Promise加载动态资源场景问题排查
问题诊断与修复方案
现有代码的核心问题
- Promise未触发resolve:你在
loadSM中创建的Promise实例全程没有调用resolve()方法,会一直处于pending状态,永远不会触发then绑定的回调逻辑。你仅完成了script标签的插入,没有监听脚本加载完成事件来触发Promise的状态变更。 - then回调参数写法错误:
loadSM().then(fixStyling())的写法会直接立即执行fixStyling函数,把函数返回值(此处为undefined)传给then,而不是将函数本身作为回调注册到Promise成功链上,正确写法应为不带括号的fixStyling。 - 隐含逻辑漏洞:就算脚本加载完成,SurveyMonkey的动态内容还需要时间渲染,此时直接调用样式修复函数大概率找不到
.survey-page-body元素,样式修改仍会失效。
可直接运行的修复代码
const fixStyling = function(){ console.log('change style'); let surveyBody = document.querySelector('.survey-page-body'); if (surveyBody) { surveyBody.style.marginTop = "-60px"; return true; } return false; } function loadSM() { return new Promise(function(resolve) { (function(t,e,s,n){ var o,a,c; t.SMCX=t.SMCX||[]; // 脚本已加载的情况直接resolve if(e.getElementById(n)) { resolve(); return; } o=e.getElementsByTagName(s); a=o[o.length-1]; c=e.createElement(s); c.type="text/javascript"; c.async=!0; c.id=n; c.src="https://widget.surveymonkey.com/collect/website/js/tRaiETqnLgj758hTBazgd1CDe7_2F_2F4snTovolmrpjpv7u54RGrphPxAqunQp3_2FUPz.js"; // 监听脚本加载完成后触发resolve c.onload = resolve; a.parentNode.insertBefore(c,a); })(window,document,"script","smcx-sdk"); }); } // 脚本加载完成后轮询检查元素是否渲染完成 loadSM().then(() => { // 每100ms检查一次元素是否存在 const checkTimer = setInterval(() => { if (fixStyling()) { clearInterval(checkTimer); } }, 100); // 10秒超时兜底,避免无限轮询占用资源 setTimeout(() => { clearInterval(checkTimer); }, 10000); });
更优实现说明
如果SurveyMonkey官方SDK提供了内容渲染完成的事件回调,优先使用官方事件触发样式修改,无需自行实现轮询,性能和准确性都更高。如果没有官方回调,上述轮询方案是兼容性最好的实现。
内容的提问来源于stack exchange,提问作者jansyb04
相关产品推荐
相关产品推荐

