JS 轨道满载承诺

问题描述 投票:0回答:1

我有一个页面,将一堆图像加载到图库中,然后通过 vanilla JS 很好地重新排列它们。

为此,脚本必须等待所有图像均已加载(或超时)。更改页面设置(如用户设置过滤器)会导致 ajax 脚本重新加载或添加图像。它们作为预渲染的 HTML 页面发送。在这种情况下,当脚本立即运行时,图像尚未完全加载,缺少脚本的关键信息,例如宽度和高度。所以我需要等到我得到这个信息(=所有图像都已完全加载)。

这是我的方法背后的想法:我尝试通过类名获取 DOM 这部分中的所有图像,为每个图像添加一个承诺,以解决图像是否完全存在或短暂超时结束的情况。我想将所有这些承诺添加到一个数组中,然后使用 Promise.All() 检查该数组。这个解决了应该调用脚本来重新排列图片。

我以前从未直接使用过 Promise,而且我对 JS 也有点菜鸟。

这是我所拥有的:

function articleImageLoadingStatusChecker() {
    var articleImages=document.getElementsByClassName("articleimage");
    var listOfPromises = [];

    articleImages.forEach(image => function(image) {
        listOfPromises.push(
            new  Promise(resolve => {
                image.addEventListener('load', () => { resolve(true); });
            }));
    });
    return listOfPromises;
}

Promise.all(articleImageLoadingStatusChecker()).then(adjustImagesForGalleryView());

这是我的问题:

  1. 运行此程序时,我希望articleImages 是或至少表现得像一个数组。如果我 console.log 它,它会返回一个类似数组的数组,并且 .length 发送一个整数。但是,我收到了奇怪的错误: 未捕获类型错误:articleImages.forEach 不是函数

  2. 我不确定我是否正确实现了promise,所以实际上可以通过Promise.all()来检查。

  3. 我认为 addEventListener('load',..) 可能会产生误导,实际上并不是要求的正确状态。当调用图库脚本时,图像可能已被缓存或已加载,因此可能不会调用侦听器。如果图像完全加载,我宁愿有一些东西可以在任何情况下解决承诺。另外,我目前不知道如何添加一些内容来在 1 秒后解决承诺,以防图像无法加载。

目前,这根本不起作用,我没有主意了。 任何建议都非常受欢迎。谢谢你。

javascript arrays promise
1个回答
1
投票

document.getElementsByClassName()
返回一个
HTMLCollection
类似数组的对象,它没有
forEach
方法。

要解决此问题,您可以使用

HTMLCollection
 函数或使用 spread 语法 
Array
Array.from()
 转换为 
...

Array.map()
是一个很好的补充,可以循环
articleImages
数组并为每个图像元素返回一个
Promise
。我建议您解决图像元素本身。这样您就可以稍后在承诺链中使用这些元素。

要在 1 秒后解决承诺,请在事件侦听器之前添加超时。在事件侦听器中,清除超时以防止每当

load
事件首次出现时运行超时回调。

在promise链中,只引用

adjustImagesForGalleryView
,不调用它(删除
()
)。

function articleImageLoadingStatusChecker() {
  const articleImages = Array.from(document.getElementsByClassName("articleimage"));

  return articleImages.map(image => 
    new Promise(resolve => {
      let timeout = setTimeout(() => {
        resolve(image);
      }, 1000);

      image.addEventListener('load', () => {
        clearTimeout(timeout);
        resolve(image);
      });
    })
  );
}

Promise
  .all(articleImageLoadingStatusChecker())
  .then(adjustImagesForGalleryView);
© www.soinside.com 2019 - 2024. All rights reserved.