Javascript 如何使图像blob URL持久化-将具有blob URL的图像附加到多个div

Javascript 如何使图像blob URL持久化-将具有blob URL的图像附加到多个div,javascript,image,async-await,fetch,blob,Javascript,Image,Async Await,Fetch,Blob,我试图从远程服务器加载一个图像,并在页面上的多个位置显示它。我首先使用fetch,创建一个新图像,并将blob转换为Image src。然而,似乎只有图像的第一次使用才显示出来 这里有什么明显的我遗漏的吗 如何让下面的代码将每个图像显示两次,而不是一次 设url1=https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Wales_versus_New_Zealand_scrum_1905_-_cropped.jpg/800px-Wa

我试图从远程服务器加载一个图像,并在页面上的多个位置显示它。我首先使用fetch,创建一个新图像,并将blob转换为Image src。然而,似乎只有图像的第一次使用才显示出来

这里有什么明显的我遗漏的吗

如何让下面的代码将每个图像显示两次,而不是一次

设url1=https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Wales_versus_New_Zealand_scrum_1905_-_cropped.jpg/800px-Wales_versus_New_Zealand_scrum_1905_-_cropped.jpg 设url2=https://upload.wikimedia.org/wikipedia/commons/thumb/4/46/France_versus_Wales_in_rugby_union_1922_-_cropped.jpg/800px-France_versus_Wales_in_rugby_union_1922_-_cropped.jpg 异步函数getImgFromUrlurl{ let response=等待获取URL; 数据=wait response.blob; 让图像=新图像; image.src=URL.createObjectURLdata; 返回图像; } document.addEventListenerDomainContentLoaded,异步函数{ 让im1=等待getimgfromurl1; 设el=document.getElementByIdpic1 el.appendChildim1 el=document.getElementByIdpic3 el.appendChildim1 让im2=等待getimgfromurl2; el=document.getElementByIdpic2 el.appendChildim2 el=document.getElementByIdpic4 el.appendChildim2 } .电网{ 显示:网格; 网格模板:自动/自动; 身高:100%; 宽度:100%; 网格间距:5px; 最大宽度:500px; } img{ 最大宽度:250px; }
您可以简单地创建img元素的副本2次。 下面我提供了一个基于给定url创建多个元素的函数

/*url: url of the images
 *ids: array of elements to be appended with the images
 */
function append_twice(url, ...ids){
    Promise.all(ids.map(async _=>await getImgFromUrl(url)))
    .then(imgs=>{
        for(let i=0;i<ids.length;i++){
            document.getElementById(ids[i]).appendChild(imgs[i]);
        }
    })
}
编辑 为了避免多次调用服务器,您可以使用的建议

function append_twice(url, ...ids){
    Promise.resolve(getData(url))
    .then(blob=>{
        return Promise.all(ids.map(async _=>await newImgFromData(blob)));
    })
    .then(imgs=>{
        for(let i=0;i<ids.length;i++){
            document.getElementById(ids[i]).appendChild(imgs[i]);
        }
    })
}

请求只会发生一次

只需创建img元素的副本2次即可。 下面我提供了一个基于给定url创建多个元素的函数

/*url: url of the images
 *ids: array of elements to be appended with the images
 */
function append_twice(url, ...ids){
    Promise.all(ids.map(async _=>await getImgFromUrl(url)))
    .then(imgs=>{
        for(let i=0;i<ids.length;i++){
            document.getElementById(ids[i]).appendChild(imgs[i]);
        }
    })
}
编辑 为了避免多次调用服务器,您可以使用的建议

function append_twice(url, ...ids){
    Promise.resolve(getData(url))
    .then(blob=>{
        return Promise.all(ids.map(async _=>await newImgFromData(blob)));
    })
    .then(imgs=>{
        for(let i=0;i<ids.length;i++){
            document.getElementById(ids[i]).appendChild(imgs[i]);
        }
    })
}

请求只会发生一次

我的建议是将获取src url和创建image元素本身的关注点分开。看起来您有一个试图附加到多个父级的单例图像元素。差不多

async function getData(url) {
  const response = await fetch(url);
  const data = await response.blob();

  return data;
}

function newImgFromData(data) {
  const new_img = new Image();

  new_img.src = URL.createObjectURL(data);

  return new_img;
}
然后使用这些函数,您可以根据需要附加任意多的新图像:

document.addEventListener("DOMContentLoaded", async function(){
  const im1 = await getData(url1);
  const im2 = await getData(url2); // These only need to be retrieved once

  // But you can use them to append children to both parent elements:
  let el = document.getElementById("pic1");
  el.appendChild(newImgFromData(im1));
  el = document.getElementById("pic3");
  el.appendChild(newImgFromData(im1));
  el = document.getElementById("pic2");
  el.appendChild(newImgFromData(im2));
  el = document.getElementById("pic4");
  el.appendChild(newImgFromData(im2));

  // You can even use the same image source as many times as you want:
  const another_el = document.getElementById("pic56");
  another_el.appendChild(newImgFromData(im1));

  const yet_another_el = document.getElementById("pic78");
  yet_another_el.appendChild(newImgFromData(im2));
});

我的建议是将获取src url和创建image元素本身的关注点分开。看起来您有一个试图附加到多个父级的单例图像元素。差不多

async function getData(url) {
  const response = await fetch(url);
  const data = await response.blob();

  return data;
}

function newImgFromData(data) {
  const new_img = new Image();

  new_img.src = URL.createObjectURL(data);

  return new_img;
}
然后使用这些函数,您可以根据需要附加任意多的新图像:

document.addEventListener("DOMContentLoaded", async function(){
  const im1 = await getData(url1);
  const im2 = await getData(url2); // These only need to be retrieved once

  // But you can use them to append children to both parent elements:
  let el = document.getElementById("pic1");
  el.appendChild(newImgFromData(im1));
  el = document.getElementById("pic3");
  el.appendChild(newImgFromData(im1));
  el = document.getElementById("pic2");
  el.appendChild(newImgFromData(im2));
  el = document.getElementById("pic4");
  el.appendChild(newImgFromData(im2));

  // You can even use the same image source as many times as you want:
  const another_el = document.getElementById("pic56");
  another_el.appendChild(newImgFromData(im1));

  const yet_another_el = document.getElementById("pic78");
  yet_another_el.appendChild(newImgFromData(im2));
});

谢谢,它看起来很整洁,但有一个小小的缺点,就是它会为图像的每个副本向服务器打额外的电话。是的,您可以结合img URL提供的单个请求的答案。谢谢,它看起来整洁,但是有一个轻微的缺点,就是它会为图像的每个副本向服务器发出额外的调用