img标签的complete属性与decode方法
<body>
<img src="a.jpg" id="pic">
<script rc="huge.js"></script>
<script>
document.getElementById("pic").onload = function() {
console.log(document.getElementById("pic").width);
}
document.title=document.getElementById("pic").width
</script>
</body>
如果huge.js执行很久
// huge.js let start = Date.now();
while (Date.now() - start < 10000) { }
此时:
- HTML 解析到
<img>,开始请求图片。 - 遇到
<script src="huge.js">,停止解析 HTML。 - huge.js 执行 10 秒。
- huge.js 执行完后,HTML 继续解析。
- 执行后面的脚本,给图片绑定
onload。 - 图片加载完成时,触发
onload。
情况2:图片已经加载完成了
这是你代码里的一个潜在问题。
如果img图片很小,或者已经在浏览器缓存中。而juge.js执行时间很长
那么可能发生:
- 图片早就下载完成。
- 但后面的 JS 还没执行到。
- 你还没有给图片绑定:pic.onload函数,等 huge.js 结束后才绑定。此时 图片的 load 事件已经过去了。结果就是pic.onload函数不会触发







if (img.decode) {
await img.decode();
} else {
await new Promise(resolve => {
if (img.complete) {
resolve();
} else {
img.onload = resolve;
}
});
}


decode() 的特点:
- 图片已经加载 → 立即返回成功
- 图片未加载 → 等待加载完成
- 图片损坏 → Promise reject
不会出现某些浏览器下第一次绘制空白的问题。

script标签是否有complete属性



如果脚本已经加载完成,后面才绑定 onload 呢?





更高级方案3:资源管理器(推荐大型项目)
很多人不知道,Google Maps SDK、Stripe SDK、PayPal SDK 都是这么干的。
class ResourceManager {
static scripts = new Map();
static load(url) {
if (!this.scripts.has(url)) {
this.scripts.set(
url,
new Promise((resolve, reject) => {
const s = document.createElement("script");
s.src = url;
s.onload = resolve;
s.onerror = reject;
document.head.appendChild(s);
})
);
}
return this.scripts.get(url);
}
}
使用:
await ResourceManager.load("huge.js");
以后任何地方,都不会重复下载,这其实是很多 SDK Loader 的实现思路。
1050

被折叠的 条评论
为什么被折叠?



