This article帮助解释了浏览器如何引入脚本,但在尝试初始化之前检查对象的最佳做法是什么?
在这里链接headroom.js时,我正在检查窗口对象是否包含它。这没关系,还是应该使用某种形式的script.onload?
<script src="js/main.js"></script>
<script src="js/libs/ScrollTrigger.min.js" defer></script>
<script src="https://unpkg.com/[email protected]/dist/headroom.min.js" async></script>
<script defer>
document.addEventListener('DOMContentLoaded', function(){
// setup ScrollTrigger (animate when item comes into view)
var trigger = new ScrollTrigger({
offset: {x:0, y:300},
once: true
});
// bind Headroom to nav
if(window.Headroom){
init_headroom();
}else{
console.log('polling for Headroom '+Date.now());
let poll_for_headroom = window.setInterval(function(){
if(window.Headroom){
clearInterval(poll_for_headroom);
init_headroom();
}
},20);
}
更多问题:2a)这种轮询会阻止UI吗? 2b)我应该检查“ScrollTrigger.min.js”是否存在?
最佳做法是将load
处理程序添加到要检查其加载的script
标记:
const headroomScript = document.querySelector('script[src*="headroom"]');
headroomScript.onload = () => {
console.log('Loaded!');
console.log(typeof window.Headroom);
};
<script src="js/main.js"></script>
<script src="js/libs/ScrollTrigger.min.js" defer></script>
<script src="https://unpkg.com/[email protected]/dist/headroom.min.js" async></script>
要检查何时加载了所有多个脚本,可以使用Promise.all
:
// this will fail because the `src` of "js/main.js" does not exist in stack snippets:
const proms = [...document.querySelectorAll('script[src]')]
.map(script => new Promise((resolve, reject) => {
script.onload = resolve;
script.onerror = reject;
}));
Promise.all(proms)
.then(() => {
console.log('All scripts are loaded!');
console.log(typeof window.Headroom);
})
.catch((err) => {
console.log('There was an error');
});
<script src="js/main.js"></script>
<script src="js/libs/ScrollTrigger.min.js" defer></script>
<script src="https://unpkg.com/[email protected]/dist/headroom.min.js" async></script>
// this will succeed:
const proms = [...document.querySelectorAll('script[src][async]')]
.map(script => new Promise((resolve, reject) => {
script.onload = () => {
console.log(script.src + ' loaded');
resolve();
};
script.onerror = reject;
}));
Promise.all(proms)
.then(() => {
console.log('All scripts are loaded!');
console.log(typeof window.Headroom);
console.log(typeof window.jQuery);
})
.catch((err) => {
console.log('There was an error');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" async></script>
<script src="https://unpkg.com/[email protected]/dist/headroom.min.js" async></script>
请注意,脚本的async
属性仅对具有外部src
的脚本有效 - 该属性对内联脚本没有影响,例如
<script async>
// do some stuff
</script>
async
标签在这里什么都不做。
这种方法和原始方法都不会阻止UI。