代码之家  ›  专栏  ›  技术社区  ›  Greg Sadetsky

onload或addEventListener的顺序以及设置图像的src是否真的很重要?

  •  3
  • Greg Sadetsky  · 技术社区  · 3 年前

    很长一段时间以来,我一直认为这是一个“绝对的事实”:

    let img = new Image();
    img.src = '... some url ...'
    img.onload = function() { console.log('onload') }
    

    错误的 ,因为 .onload 可能无法调用处理程序。使用附加处理程序也是一样的 .addEventListener('load', function() ... ) 设置后 .src :可能不起作用。(看这个 example answer 声明如下:“…在为src属性赋值之前添加事件侦听器…”)


    这个问题的背景:我找到了一个设置的例子 .src 打电话之前 .addEventListener 在流行的p5.js库中,特别是 here 。我想解决这个问题并提交一个PR。但是,我也想创建一个单元测试 失败 使用当前代码(设置 .src = 打电话之前 .addEventListener 通过 用我的补丁。

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


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

    (function f() {
      let i = new Image();
      i.src = '//placekitten.com/10/10';
      document.querySelector('body').appendChild(i);
      
      let out = 0;
      for(let i = 0; i < 1000000000; i++) { out *= i * 100 - out * 2; } // just to delay
    
      i.onload = function() { console.log('onload') }
      i.addEventListener('load', function() { console.log('load event') });
    })();
    

    1000000000次迭代循环需要几秒钟才能完成,因为我正试图获得 Image 元素和要尽早加载的图像URL,以便 .加载 .addEventListener 处理程序将失败。。。但它们有效!

    我试着用一个很短的数据URL代替placekitten.com,结果是一样的。在运行测试代码之前,我尝试加载placekitten.com和数据URL图像(以确保这些图像被缓存),但这也不起作用。

    我唯一能得到的方法 .加载 .addEventListener 不被调用的处理程序是将它们包装在 setTimeout ...


    JavaScript的单一线程性是否使以下“事实”无效 .src 应该始终在设置事件侦听器之后进行设置吗?或者这是现代浏览器中发生的变化,而在旧的浏览器中也是如此 .src 在连接侦听器之前有时会失败?谢谢

    1 回复  |  直到 3 年前
        1
  •  2
  •   Bergi Ray Nicholus    3 年前

    顺序无关紧要。这个 load 事件总是异步激发(在事件循环中排队的 the loading algorithm ),在同步执行完成后,将评估安装了哪些事件侦听器,并且仅在那时才需要执行这些侦听器。

    给定 answer that you linked 尤其是 image.onload event and browser cache / jQuery callback on image load (even when the image is cached) ,如果图像是从缓存加载的,则较旧的浏览器可能已同步(或根本没有)触发事件。