刚学js时候,在html中引入了js的外部文件,运行时却发现无法实现验证码刷新功能,初步怀疑是因为路径写错了,后面检查发现并非这个原因。
调试了很多次始终不行,直到在网上看到有人说是因为js中的同步加载问题导致的。
在网上找了很多资料,所以我们来了解一下js中的同步加载和异步加载问题。
1.同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止了后续的解析,因此停止了后续的文件加载(如图像)、渲染、代码执行。
这是我们刚学习js时的写法,直接引入外部文件:
<script src=""></script>//引入外部文件js
<script type="text/javascript">
console.log('hello world');
</script>
或者直接插入到html代码中使用:
<script type="text/javascript">//直接在html中插入使用
console.log('hello world');
</script>
比如,如果位置放置不当,将严重影响浏览器渲染的效率,所以我们一般把javaScript放在页面的最底部,避免浏览器在解析javaScript的时候出现资源阻塞。如果把script标签放在页面的首部且javaScript文件加载需要花很长的时间的话,页面会出现较长时间的白屏。而这代码中有某种原因加载时造成的阻塞,就会导致后面的html页面一直无法渲染和刷新(我自己就是)。
但是同步加载按照顺序逐个加载资源,代码的执行流程易于理解和控制。对于简单的场景,同步加载可以更容易地编写和维护代码。比较安全。
2.异步加载,简单来说就是在执行js代码时也可以去执行其他的代码,例如加载js时还可以渲染解析html页面。异步加载又叫非阻塞,浏览器在下载 JS 同时,还会继续进行后续页面的处理,比如即使因为js文件存放的位置导致的同步加载问题,也可以通过异步加载去去除影响。
一般实现异步加载有4种方法:
(1)通过给js添加defer属性可以实现异步加载,但是defer属性只能在IE9以下版本才能使用。
<script defer>//添加一个defer属性
//js代码
</script>
(2)通过给js添加async属性,但async属性是HTML5新增的,使用时需注意兼容性问题。
<script async="async">//添加一个async属性
</script>
async/await 是 ES2017 引入的异步编程语法糖,它可以让异步代码看起来像同步代码,更易读。
(3)使用 Promise 对象:Promise 是 JavaScript 中处理异步操作的一种机制,它可以包装一个异步操作,并提供了链式调用的语法。
Promise 对象:Promise 提供了一种更优雅的方式来处理异步操作,通过链式调用的方式使代码易于阅读和维护。它也提供了处理成功和失败情况的机制,通过 .then()
和 .catch()
方法来处理结果和错误。Promise 也可以与其他异步操作组合使用,形成更复杂的异步流程。
function loadData() {
return new Promise(function(resolve, reject) {
// 异步加载数据
// 加载完成后调用 resolve 处理结果
// 加载失败时调用 reject 处理错误
});
}
// 使用 Promise 处理异步加载的数据
loadData()
.then(function(data) {
// 处理数据
})
.catch(function(error) {
// 处理错误
});
(4)使用回调函数(Callback):将异步操作封装在一个函数中,并将回调函数作为参数传递给该函数。当异步操作完成时,调用回调函数来处理结果。
回调函数(Callback):回调函数是最早被广泛使用的异步处理方法之一,它可以在不支持Promise 或 async/await 的旧版 JavaScript 中使用。然而,使用回调函数嵌套多层的代码可能会导致回调地狱(Callback Hell),使代码难以阅读和维护。因此,在处理复杂的异步逻辑时,回调函数可能不是最佳选择。
function loadData(callback) {
// 异步加载数据
// 加载完成后调用回调函数
callback(data);
}
// 使用回调函数处理异步加载的数据
loadData(function(data) {
// 处理数据
});