Javascript 加载不带“的图像”;新图像();

Javascript 加载不带“的图像”;新图像();,javascript,image,loading,Javascript,Image,Loading,我正在尝试用JavaScript加载图像: loadImage(src,img){ 返回新承诺((解决、拒绝)=>{ img.onload=解析; img.onerror=拒绝; img.src=src; }); } 以前已经创建了img,但DOM中还不存在。加载后应将其追加 我的问题:据我所知,它实际上不会加载图像,因为元素还不是DOM的一部分 我尝试使用new Image(),因为这将在插入DOM之前加载图像源: loadImage(src,img){ 返回新承诺((解决、拒绝)=>{

我正在尝试用JavaScript加载图像:

loadImage(src,img){
返回新承诺((解决、拒绝)=>{
img.onload=解析;
img.onerror=拒绝;
img.src=src;
});
}
以前已经创建了
img
,但DOM中还不存在。加载后应将其追加

我的问题:据我所知,它实际上不会加载图像,因为元素还不是DOM的一部分


我尝试使用
new Image()
,因为这将在插入DOM之前加载图像源:

loadImage(src,img){
返回新承诺((解决、拒绝)=>{
var tmp=新图像();
tmp.onload=解析;
tmp.onerror=拒绝;
tmp.src=src;
img.src=src;
});
}
然而,这做了两次加载和感觉车

我需要保留(并使用)img元素,因为其他事件处理程序和属性都附加到它


加载图像并在完成后解析承诺时,我可以做些什么?

如果我理解正确,您希望在加载完成后渲染图像吗?也许只是在“loadImage”函数中创建图像,然后在“onload”中进行适当的附加。下面是我所想的一个例子:

const loadImage = (src, parentEl) => {
const img = document.createElement('img')
img.src = src
img.onload = () => {
  parentEl.appendChild(img)
 }
}

const parentEl = document.getElementById('parent')
loadImage('https://fakeimg.pl/640x360', parentEl)

不确定第二种方法有什么问题,以及为什么您认为它有问题。我可以想象,如果图像还不在缓存中,它会加载两次:如果触发同时加载两个图像,浏览器无法知道URL的缓存参数,应该分别为这两个元素加载。但是,如果您按顺序加载它们,第二个应该从缓存中提取,而不是发出单独的请求,除非您的服务器异常,并且提供禁止缓存的头

函数loadImage(src,img){
返回新承诺((解决、拒绝)=>{
var tmp=新图像();
tmp.onload=()=>{
img.src=src;
解决();
};
tmp.onerror=拒绝;
tmp.src=src;
});
}
加载图像(“https://via.placeholder.com/350x150,document.getElementById('foo')

我认为你的假设是错误的。加载图像时不需要将其附加到DOM

我稍微修改了您的函数,使其使用图像标记而不是加载事件进行解析,并且似乎工作正常:

const loadImage=(src,img)=>{
返回新承诺((解决、拒绝)=>{
img.src=src
img.onload=()=>{
解决(img);
}
img.onerror=拒绝;
})
}
我是这样测试的:

const img=document.createElement('img');
loadImage('http://deelay.me/1500/https://fakeimg.pl/640x360",img)
。然后((img)=>{
const parent=document.getElementById('parent');
document.getElementById('parent').append(img);
const text=document.createElement('p');
text.innerText=“承诺现在已解决”;
parent.append(文本);
})
deelay.me
为图像加载添加了人为延迟,因此您可以看到图像实际上已加载,并且使用promise,仅在加载后才附加到DOM

希望这有帮助

小提琴:

那么为什么不直接设置图像呢?
tmp.src=src;img.src=src这不会预加载…img.src的设置必须在onload调用中完成。@epascarello我也这么认为,但在我的开发工具中,我可以看到源代码被提取了两次。不知道为什么。。。此外,我不能直接设置图像,因为它是一个更大结构的一部分,取决于加载的图像。很遗憾,这不是那么容易。该图像只是HTML结构的一部分,即lightbox。这个结构是通过JavaScript创建的。我只想在图像加载后将结构附加到DOM中。我不能使用你的方法,因为它创建了一个新的图像元素。我需要使用已经存在的元素。否则,这将很容易:D@AndreasRemdt我很困惑-在加载图像之前,您不想将其添加到DOM中,但是您已经在DOM中有了一个图像,您必须重新使用它吗?除非我弄错了,否则您可以使用此方法替换以前的图像,但您可以删除旧图像,并在onload事件中追加新图像。@VLAZ想象一下:
var template=''。图像还不是DOM的一部分,它是我的JavaScript的一部分。一旦加载,它应该在DOM中。很有趣!我在DevTools中禁用了缓存,因为我想通过节流测试慢速连接。即使使用您的方法,图像也会在网络中提取两次。那么,禁用的缓存可能是问题所在吗?如果禁用缓存,那么显然将无法在其中找到第二个图像:)禁用缓存的唯一方法是使用AJAX/获取图像源并将其转换为类似的数据URL,然后将数据URL用于
img.src
;通过这种方式,您可以明确地控制流量;尽管如此,你还是受到XSS的限制,感觉很恶心。请帮自己一个忙,并使用适当的服务器配置进行测试,以确保-映像缓存存在是有原因的:德威尔,今天我学到了一些新东西。我将使用
deelay.me
来模拟网络延迟,并让缓存保持打开状态:D非常感谢!谢谢,我想我已经弄明白了,这似乎是缓存的问题。然而,这个
deelay.me
服务非常方便,从现在起,我将使用它来模拟网络延迟。