如何检查图片是否存在?

时间:2018-12-07 19:45:27

标签: javascript jquery

我有一些应在其中某些页面设置图像的应用程序。这些图像在服务器上,每个图像都附加了唯一的ID。这是图像名称的示例:

AA_image1.jpg
AB_image1.jpg
AC_image1.jpg
AD_image1.jpg
AE_image1.jpg

我看到了以前的开发人员做了什么,以及他们如何检查图像的存在。他们使用了具有ID和图片名称的JSON文件。这是该代码的示例:

var images = [{
    "id": "AA",
    "image": "AA_image1.jpg"
  },
  {
    "id": "AB",
    "image": "AB_image1.jpg"
  },
  {
    "id": "AC",
    "image": "AC_image1.jpg"
  },
  {
    "id": "AD",
    "image": "AD_image1.jpg"
  },
  {
    "id": "AE",
    "image": "AE_image1.jpg"
  }
];

var imgID = "AC";
var imgPrimary = "AC_image1.jpg";
var found = false;
var imgDefault = "default.jpg";

for (i = 1; i < images.length; i++) {
  if (images[i].id == imgID && (images[i].image).toLowerCase() == (imgID + '_image1.jpg').toLowerCase()) {
    found = true;
    break;
  }
}

if (found === true) {
  console.log(imgPrimary);
} else {
  console.log(imgDefault);
}

上面的示例似乎非常简单,但是我担心的是,如果图像从文件夹中删除并且JSON文件未更新?在这种情况下,我们将加载不存在的图像而不是默认图像。我想知道这种方法是否会更好:

var imgID = "AC";
var imgNames = [imgID + '_image1','default'];
var imgResults = {};

for(var i = 0;  i < imgNames.length; i++){
   checkImage( imgNames[i] );
}

function checkImage( imgName, keyName ) {
    $.ajax({
        type: "GET",
        async: true,
        url: "images/"+imgName+".jpg",
    }).done(function(message,text,jqXHR){
         imgResults[imgName] = true;
    }).fail(function(jqXHR, textStatus, errorThrown){
         imgResults[imgName] = false;
    });
 }

以下是imgResults在流程完成后的示例:

console.log(imgResults);

控制台结果:

{
  "default": true,
  "AG_image1": false
}

我在第二个示例中遇到的唯一问题是,如果我尝试根据键检查结果,那么我将变得不确定。这是示例:

console.log(imgResults["AG_image1"]);

这是控制台中的结果:

undefined

我不确定这两者之间哪个更好,更安全。如果有人有建议,请告诉我。

2 个答案:

答案 0 :(得分:3)

这可能是处理JS中丢失图像的最短代码。 imagePad是对要在其中显示图像的DOM元素的引用。

var img = new Image();
img.addEventListener('error', function (e) {
    // Image not found, show the default
    this.src = iconBase + 'gen.png';
});
img.addEventListener('load', function () {
    imagePad.appendChild(img);
}
img.src = 'the_given_src';

答案 1 :(得分:1)

AJAX请求默认是异步的

尝试时无法搜索imgResults对象的原因是因为AJAX请求是异步的,并且当您尝试访问结果时请求尚未完成。您需要等待请求完成才能继续。

console.log显示结果的原因是因为console.log是惰性的,并且直到您在开发工具中对其进行扩展之前都不会评估该对象,console.dir将向您显示一个空对象那一点。

此外,由于您有多个请求要等待,因此您将要创建一个Promise数组,其中每个Promise对应于每个请求的负载/失败,然后使用Promise.all等待在完成结果之前完成所有承诺。

验证资源是否存在

要验证资源是否存在,可以使用HEAD请求而不是GET请求,以防止无故加载整个图像。也不需要依赖诸如jQuery之类的大型库来处理AJAX请求,因为在当今时代,XMLHttpRequest得到了很好的支持。

class ResourceValidator extends EventTarget {
  constructor(target) {
    super()
    this.target = target
    this._ready = false
    this._valid = false
    this.validate()
  }
  validate() {
    const request = new XMLHttpRequest()
    request.addEventListener('load', event => {
        this._ready = true
        this._valid = true
        this.dispatchEvent(new Event('ready'))
    })
    request.addEventListener('error', event => {
        this._ready = true
        this.dispatchEvent(new Event('ready'))
    })
    request.open('HEAD', this.target)
    request.send()
  }
  get ready() {
    return new Promise(resolve => {
      if(this._ready === true) resolve(true)
      else this.addEventListener('ready', _ => resolve(true))
    })
  }
  get valid() {
    return new Promise(resolve => {
      if(this._ready === true) resolve(this._valid)
      else this.addEventListener('ready', _ => resolve(this._valid))
    })
  }
}

async function validateImageSources(sources) {
  const results = {}
  const promises = []

  for(let source of sources) {
     const validator = new ResourceValidator(source)
     const promise = validator.valid
     promise.then(valid => results[source] = valid)
     promises.push(promise)
  }
  
  await Promise.all(promises)
  
  return results
}

validateImageSources([
  'https://picsum.photos/200',
  'https://nosuchaddress.io/image.png'
]).then(results => {
  console.log(results)
  console.log(results['https://picsum.photos/200'])
})