javascript - 检查脚本是否已加载(并且对象存在于窗口空间中)的最佳实践?
问题描述
本文帮助解释了浏览器如何拉入脚本,但是在尝试初始化对象之前检查对象是否存在的最佳实践是什么?
在此处链接 headroom.js 时,我目前正在检查窗口对象是否包含它。这可以吗,还是我应该使用某种形式的script.onload?
<script src="js/main.js"></script>
<script src="js/libs/ScrollTrigger.min.js" defer></script>
<script src="https://unpkg.com/headroom.js@0.9.4/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) 这种轮询会阻塞用户界面吗?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/headroom.js@0.9.4/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/headroom.js@0.9.4/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/headroom.js@0.9.4/dist/headroom.min.js" async></script>
请注意,async
脚本的属性仅对具有外部的脚本有效src
- 该属性对内联脚本没有影响,例如
<script async>
// do some stuff
</script>
标签在async
这里什么也不做。
这种方法和您原来的方法都不会阻塞 UI。
推荐阅读
- kubernetes - 如何创建令牌长度更短的 k8s 服务帐户?
- sql - 如何使 CREATE DATABASE 命令在 SQL 中可重新运行?
- r - 不明白为什么 dplyr 中的填充函数在调用时显示包含该对象的数据集时说该对象不存在
- tinymce - 有没有办法在 Symfony 5.1 中集成 TinyMCE 和 EasyAdmin 3.x Bundle
- javascript - 如何使 axios 获取请求同步?
- java - 每当我尝试登录我的应用程序时,就会发生这些 sql 错误 1146。如何解决?
- vue.js - Ionic 5,Vue 3 - 如何在 setup() 中使用 Ionic 生命周期挂钩?
- python - 合并子串
- python - 如何在列表中保存多个 random.choice 生成的“数据”并打印出来
- python - 如何在 Flask 中访问函数的返回变量