img与script标签onload函数可能错过的解决办法

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) { }

此时:

  1. HTML 解析到 <img>,开始请求图片。
  2. 遇到 <script src="huge.js">,停止解析 HTML。
  3. huge.js 执行 10 秒。
  4. huge.js 执行完后,HTML 继续解析。
  5. 执行后面的脚本,给图片绑定 onload
  6. 图片加载完成时,触发 onload

情况2:图片已经加载完成了

这是你代码里的一个潜在问题。

如果img图片很小,或者已经在浏览器缓存中。而juge.js执行时间很长

那么可能发生:

  1. 图片早就下载完成。
  2. 但后面的 JS 还没执行到。
  3. 你还没有给图片绑定: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 的实现思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值