长期以来,我一直将其视为“绝对真理”:
\nlet img = new Image();\nimg.src = \'... some url ...\'\nimg.onload = function() { console.log(\'onload\') }\nRun Code Online (Sandbox Code Playgroud)\n是错误的,因为.onload处理程序可能不会被调用。.addEventListener(\'load\', function() ... )设置后使用附加处理程序也是如此.src:它可能不起作用。(请参阅此示例答案,说明:“...在为 src 属性分配值之前添加事件侦听器...”)
这个问题的背景:我在流行的 p5.js 库中找到了一个.src调用之前设置的示例,特别是在这里。我想解决这个问题并提交 PR。但是,我还想创建一个单元测试,该测试在当前代码(调用之前的设置)中失败,并在我的修复中通过。.addEventListener.src =.addEventListener
然而!我还没能真正看到.src之前的设置在什么情况下实际上失败了......!
这是一些代码来演示我的意思:
\n(function f() {\n let i = new Image();\n i.src = \'//placekitten.com/10/10\';\n document.querySelector(\'body\').appendChild(i);\n \n let out = 0;\n for(let i = 0; i < 1000000000; i++) { out *= i * 100 - out * 2; } // just to delay\n\n i.onload = function() { console.log(\'onload\') }\n i.addEventListener(\'load\', function() { console.log(\'load event\') });\n})();\nRun Code Online (Sandbox Code Playgroud)\n1000000000 次迭代循环需要几秒钟才能完成,因为 \xc2\xa0I\ 正在尝试将元素Image添加到 DOM 并尽早加载图像 URL,以免.onload和.addEventListener处理程序失败......但是他们工作!
我尝试使用非常短的数据 URL 而不是 placekitten.com,结果相同。我尝试在运行测试代码之前加载 placekitten.com 和数据 URL 图像(以确保这些图像被缓存),但这也不起作用。
\n.onload我可以让和.addEventListener处理程序不被调用的唯一方法是将它们包装在setTimeout......
JavaScript 的单线程性是否使.src设置事件侦听器后应始终设置的“真相”失效?或者这是现代浏览器中发生的变化,并且在旧浏览器中曾经如此设置.src附加侦听器之前进行设置有时会失败?谢谢!
顺序并不重要。在同步执行完成后,事件load始终以异步方式触发(通过加载算法在事件循环中排队),并且只有在那时才会评估安装了哪些事件侦听器并需要执行。
鉴于您链接的答案,尤其是image.onload 事件和浏览器缓存/图像加载时的 jQuery 回调(即使图像已缓存),如果图像是,旧版浏览器似乎可能已同步触发该事件(或根本不触发)从缓存加载。
| 归档时间: |
|
| 查看次数: |
623 次 |
| 最近记录: |