我在下面写的函数是否足以在大多数(如果不是全部的话)当前常用的浏览器中预加载图像?

function preloadImage(url)
{
    var img=new Image();
    img.src=url;
}

我有一个图像URL数组,我循环遍历并为每个URL调用preloadImage函数。


当前回答

这就是我所做的,用承诺:


const listOfimages = [
    {
        title: "something",
        img: "https://www.somewhere.com/assets/images/someimage.jpeg"
    },  
    {
        title: "something else",
        img: "https://www.somewhere.com/assets/images/someotherimage.jpeg"
    }
];

const preload = async () => {
    await Promise.all(
        listOfimages.map(
            (a) =>
                new Promise((res) => {
                    const preloadImage = new Image();
                    preloadImage.onload = res;
                    preloadImage.src = a.img;
                })
        )
    );
}

其他回答

我建议你使用try/catch来防止一些可能的问题:

OOP:

    var preloadImage = function (url) {
        try {
            var _img = new Image();
            _img.src = url;
        } catch (e) { }
    }

标准:

    function preloadImage (url) {
        try {
            var _img = new Image();
            _img.src = url;
        } catch (e) { }
    }

另外,虽然我喜欢DOM,但老式的愚蠢浏览器可能会在你使用DOM时遇到问题,所以恕我直言,与freedev的贡献相反,完全避免使用DOM。Image()在旧的垃圾浏览器中有更好的支持。

是的,这是可行的,但是浏览器会限制(4-8之间)实际的调用,因此不会缓存/预加载所有想要的图像。

更好的方法是在使用图像之前调用onload,如下所示:

function (imageUrls, index) {  
    var img = new Image();

    img.onload = function () {
        console.log('isCached: ' + isCached(imageUrls[index]));
        *DoSomething..*

    img.src = imageUrls[index]
}

function isCached(imgUrl) {
    var img = new Image();
    img.src = imgUrl;
    return img.complete || (img .width + img .height) > 0;
}

这是最初的答案,但使用了更现代的ES语法:

let preloadedImages = [];
export function preloadImages(urls) {
    preloadedImages = urls.map(url => {
        let img = new Image();
        img.src = url;
        img.onload = () => console.log(`image url [${url}] has been loaded successfully`);
        
        return img;
    });
}
const preloadImage = src => 
  new Promise((resolve, reject) => {
    const image = new Image()
    image.onload = resolve
    image.onerror = reject
    image.src = src
  })


// Preload an image
await preloadImage('https://picsum.photos/100/100')

// Preload a bunch of images in parallel 
await Promise.all(images.map(x => preloadImage(x.src)))

在我的例子中,为onload事件添加一个回调函数是有用的:

function preloadImage(url, callback)
{
    var img=new Image();
    img.src=url;
    img.onload = callback;
}

然后包装它的情况下,一个url数组的图像被预加载回调对all是完成的: https://jsfiddle.net/4r0Luoy7/

function preloadImages(urls, allImagesLoadedCallback){
    var loadedCounter = 0;
  var toBeLoadedNumber = urls.length;
  urls.forEach(function(url){
    preloadImage(url, function(){
        loadedCounter++;
            console.log('Number of loaded images: ' + loadedCounter);
      if(loadedCounter == toBeLoadedNumber){
        allImagesLoadedCallback();
      }
    });
  });
  function preloadImage(url, anImageLoadedCallback){
      var img = new Image();
      img.onload = anImageLoadedCallback;
      img.src = url;
  }
}

// Let's call it:
preloadImages([
    '//upload.wikimedia.org/wikipedia/commons/d/da/Internet2.jpg',
  '//www.csee.umbc.edu/wp-content/uploads/2011/08/www.jpg'
], function(){
    console.log('All images were loaded');
});