问题描述
我有一个包含多个组件的 AEM 页面,这些组件有一个 .js 文件,其中包含一个包含所有客户端逻辑的函数。然后我们在组件的 HTML 中调用该函数:
<script>
window.bootstrap_component(function() {
init_component_name();
});
</script>
如前所述,init_component_name 是一个包含我们需要的所有逻辑的函数的名称:
function init_component_name() {
//DO STUFF
}
包装器 bootstrap_component 函数在我们所有页面的共享 head.html 中定义为:
<script>
window.bootstrap_component = function (handler) {
if (typeof handler === 'function') {
if (document.readyState === "complete" || document.readyState === "loaded" || document.readyState === "interactive") {
handler();
} else {
document.addEventListener("DOMContentLoaded",function() {
handler();
});
}
}
}
</script>
这工作正常,我们没有任何实际问题,但我们最近开始使用 Bugsnag 进行错误监控和报告,我们收到几乎每个组件的报告,在页面上说 ReferenceError 所以/和/所以 init_component_name() 不是定义。
我认为发生这种情况的原因是因为 init_component_name() 函数没有在 script 标签中声明,并且因为这个 function(init_component_name) 已经附加到它正在执行的窗口对象上,你看不到任何控制台错误。
<script>
window.bootstrap_component(function() {
window.init_component_name();
})
</script>
我的一个同事想为 init_component_name 函数添加一个像 1ms 这样的超时时间,但它让我感到不适。有没有更明智的做法?
解决方法
如果我是对的,会修改这些脚本标签来像这样工作吗?
window.bootstrap_component(function() {
window.init_component_name();
})
是的,但是您会遇到将多个数据写入全局命名空间 window
的问题,这并不理想。如果另一个第三方脚本决定覆盖它怎么办?
理想情况下,您应该有一个命名空间并将所有内容都放在那里,并且只将该命名空间写入 window
。
window.something = {};
something.bootstrap_component = { //...
和
something.init_component_name = () => {
//DO STUFF
}
或者更好的是,使用 modules(尽管这需要一些简单的代码重构)。
不要做超时黑客。真的,真的太可怕了;如果脚本由于某种原因加载时间超过一秒怎么办?您还强迫您的 UI 等待一秒钟,这通常是不必要的。这种 hack 往往体现在没有正确考虑时间顺序和范围的地方。