使用jQuery替换图片src时控制台日志重复输出问题排查
问题场景前提
- 页面包含两张图片,ID分别为
#me1和#me2 - 两张图片初始
src属性分别指向1.jpg和2.jpg - 点击
#me1时,通过jQuery向PHP脚本randim.php发起GET请求,脚本返回随机选中的图片文件名,需将该文件名设置为#me2的src属性值 - 点击
#me2时执行相同逻辑,替换#me1的src属性值 - 交互规则:点击任意一张图片仅修改另一张图片的
src,不修改被点击图片自身的资源 - 日志要求:在替换图片
src前向控制台输出操作日志,待目标图片加载完成后再次输出加载完成日志
实现代码
<!DOCTYPE html> <html lang="en-GB"> <head> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script> var nextimg; function start() { console.log("First #me1 image is " + $('#me1').attr("src")); console.log("First #me2 image is " + $('#me2').attr("src")); } function clickedme1() { console.log("#me1 has been clicked, need to replace the image in #me2"); nextimg = $.ajax({ type: "GET", url: "randim.php", async: false }).responseText; console.log("Next image is for #me2 is " + nextimg); $('#me2').attr("src", nextimg); $('#me2').on("load", function() { console.log("Finished loading " + nextimg + " in #me2"); }); } function clickedme2() { console.log("#me2 has been clicked, need to replace the image in #me1"); nextimg = $.ajax({ type: "GET", url: "randim.php", async: false }).responseText; console.log("Next image is for #me1 is " + nextimg); $('#me1').attr("src", nextimg); $('#me1').on("load", function() { console.log("Finished loading " + nextimg + " in #me1"); }); } </script> <style>#me1, #me2 { width: 400px; height: 400px }</style> </head> <body> <img id="me1" onClick="clickedme1()" src="images/1.jpg"> <img id="me2" onClick="clickedme2()" src="images/2.jpg"> <script>window.onload = start();</script> </body> </html>
异常现象
- 代码功能整体运行正常,但控制台日志存在重复输出问题,点击次数越多,单条日志的重复条数越多,该问题在Chrome、Firefox浏览器下均可复现。
- 排查Web服务器访问日志无异常,不存在多余请求:每次点击仅发起1次
randim.php请求,后续对应发起1次图片资源请求。 - 已知
randim.php脚本运行稳定可靠,服务器环境为Ubuntu 20.04.4 LTS上的Apache/2.4.41,需定位重复日志问题的诱因。
问题诱因
重复日志的核心原因是load事件监听器被重复绑定,且从未解绑历史绑定的监听器:
- jQuery的
.on()方法绑定事件时,不会覆盖元素上已绑定的同类型事件,只会在事件回调队列里追加新的处理函数。 - 现有代码每触发一次点击逻辑,就会给要替换src的目标图片绑定一个新的load事件回调,全程没有通过
.off()方法移除之前绑定过的同类型load回调。 - 首次点击对应图片时,目标图片会被绑定1个load回调,等图片加载完成后自然只输出1次加载完成日志;第二次点击时,目标图片上已经累计2个load回调,图片加载完成后两个回调会依次执行,就会输出2条重复日志;点击次数越多,累计绑定的回调数量越多,日志重复的条数就会同步增长。
- 由于每次点击确实只发起1次
randim.php请求、1次图片资源请求,服务器侧不会记录到多余请求,和排查到的服务器日志现象完全吻合。
内容的提问来源于stack exchange,提问作者Displayname71
相关产品推荐
相关产品推荐

