onload 或 addEventListener 的顺序以及设置图像的 src 的顺序实际上重要吗?

Gre*_*sky 5 javascript dom

长期以来,我一直将其视为“绝对真理”:

\n
let img = new Image();\nimg.src = \'... some url ...\'\nimg.onload = function() { console.log(\'onload\') }\n
Run Code Online (Sandbox Code Playgroud)\n

错误的,因为.onload处理程序可能不会被调用。.addEventListener(\'load\', function() ... )设置后使用附加处理程序也是如此.src:它可能不起作用。(请参阅此示例答案,说明:“...在为 src 属性分配值之前添加事件侦听器...”)

\n
\n

这个问题的背景:我在流行的 p5.js 库中找到了一个.src调用之前设置的示例,特别是在这里。我想解决这个问题并提交 PR。但是,我还想创建一个单元测试,该测试在当前代码(调用之前的设置)中失败,并在我的修复中通过。.addEventListener.src =.addEventListener

\n

然而!我还没能真正看到.src之前的设置在什么情况下实际上失败了......!

\n
\n

这是一些代码来演示我的意思:

\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})();\n
Run Code Online (Sandbox Code Playgroud)\n

1000000000 次迭代循环需要几秒钟才能完成,因为 \xc2\xa0I\ 正在尝试将元素Image添加到 DOM 并尽早加载图像 URL,以免.onload.addEventListener处理程序失败......但是他们工作!

\n

我尝试使用非常短的数据 URL 而不是 placekitten.com,结果相同。我尝试在运行测试代码之前加载 placekitten.com 和数据 URL 图像(以确保这些图像被缓存),但这也不起作用。

\n

.onload我可以让和.addEventListener处理程序不被调用的唯一方法是将它们包装在setTimeout......

\n
\n

JavaScript 的单线程性是否使.src设置事件侦听器后应始终设置的“真相”失效?或者这是现代浏览器中发生的变化,并且在旧浏览器中曾经如此设置.src附加侦听器之前进行设置有时会失败?谢谢!

\n

Ber*_*rgi 3

顺序并不重要。在同步执行完成后,事件load始终以异步方式触发(通过加载算法在事件循环中排队),并且只有在那时才会评估安装了哪些事件侦听器并需要执行。

鉴于您链接的答案,尤其是image.onload 事件和浏览器缓存/图像加载时的 jQuery 回调(即使图像已缓存),如果图像是,旧版浏览器似乎可能已同步触发该事件(或根本不触发)从缓存加载。