为什么Image()。width = 0甚至服务器上也存在图像

时间:2019-03-11 04:14:51

标签: javascript ionic-framework

我正在Ionic 3上执行一项功能,以在用户头像未上传自己的头像的情况下加载具有缓存和默认头像的用户头像。这是我的代码,后面跟着这个https://gist.github.com/pabloleonalcaide/1e8ece835ea689894dd37a44f0ce7134

public get_UserIcon(id, cache = null) {
    cache = cache || Math.floor(new Date().getMinutes() / 6); //cache for 10 minutes
    let url = `${server}UserIcon${id}.jpg?c=${cache}`;
    let image = new Image();
    image.src = url;
    if(image.width != 0){ // check if image exist
      return url;
    }else{
      return DefaultImage;
    }
  }

但是,当我尝试运行代码时,image.width将显示0并返回默认图像,即使该图像在服务器上也是如此。有时它将显示正确的宽度并返回正确的化身。

我尝试使用

img.onload = () => { 
 return url;
}
img.onerror = () =>{
 return DefaultImage;
}

但是我不确定为什么使用上面的代码会让我的应用程序滞后,似乎卡在了JS运行时堆栈中。我试图将console.log放在onload和onerror中,但是没有一个被调用。

有人知道如何解决吗?谢谢

更新

我的用法将是这样,以便该功能将检查图像是否存在并返回用户头像或默认头像。

<img [src]="get_UserIcon(id)">

2 个答案:

答案 0 :(得分:1)

因为加载图像(如任何资源)是异步任务。

在您请求图像的宽度时,对服务器的请求甚至可能还没有离开您的网卡,而浏览器需要来自该服务器的响应,并且能够对其进行解码和解析媒体的元数据。

您必须等待图像加载后才能获得此信息:

var img = new Image();
img.src = 'https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png';
console.log('before', img.width);
// wait for the iamge has loaded
img.onload = e => console.log('after', img.width);

因此,您的函数应包含任务的异步性,例如通过返回Promise:

const DefaultImage = 'default'
function get_UserIcon(id, cache = null) {
    cache = cache || Math.floor(new Date().getMinutes() / 6); //cache for 10 minutes
    const url = "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png";
    const image = new Image();
    return new Promise((res, rej) => {
      image.onload = e => res(url); // if onload fires, width is not 0
      image.onerror = e => res(DefaultImage);
      image.src = url;
    });
  }
  
get_UserIcon().then(console.log);

答案 1 :(得分:0)

我不确定我是否阅读正确。但这块:

if(image.width != 0){ // check if image exist
  return url;
}else{
  return DefaultImage;
}

应该在您的image.onload函数中。否则,由于您没有任何时间加载图像,因此宽度每次都会为0。

代替返回url,您也应该调用某种回调函数。它实际上将网址返回为空。

下面是一个简单的小提琴,向您展示我的意思:https://jsfiddle.net/2sLu641j/