等待在JavaScript中完成图像加载

时间:2016-06-16 08:54:14

标签: javascript html5 image canvas

我正在使用JavaScript加载图片。像这样:

images[0]=new Image();
images[0].onload=function(){loaded++;console.log(loaded)};
images[0].src="assets/img/image.png";

当我查看日志时,我看到所有图像都被很好地加载,因为"加载了#34;变量随着每个加载的图像而增加。

但是我想停止执行任何进一步的操作,直到这个数量达到它的最大值,所以在设置图像之后,我放置了一段时间。

while(loaded<11){
    document.getElementById("test").innerHTML="Loading "+loaded+"/11";
    console.log(loaded);
}
//Some code here which should only run after everything has been loaded
//In other words: when the statement in the while cycle becomes false

然而,我的浏览器只是崩溃,因为while似乎陷入无限循环。当我查看日志时,我看到&#34; 0&#34;写了1000次,之后,数字从1到11(这意味着图像实际上已经加载了,但是while并不关心它,并且崩溃的速度比它可能发生得快)。

我相信我试图在这里使用的方法不是解决此问题的正确方法。

如果在加载网站所需的每项资产之前,我怎么能暂停一切?

3 个答案:

答案 0 :(得分:3)

我个人讨厌使用while()......我认为最简单的方法就是使用事件监听器。

var img = new Image;
img.addEventListener("load", function () {

//Img loaded

});
img.src= e.target.result;

答案 1 :(得分:2)

Javascript是单线程的。这意味着如果添加一个事件侦听器,该侦听器将在当前执行完成之前不会运行。因此,如果您启动一个依赖于事件来结束它的循环,它将永远不会发生,因为事件永远不会触发,因为当前执行阻止它运行。此外,事件异步放置在调用堆栈上,因此如果执行速度低于事件触发速率(在调用堆栈上调用),则还会导致页面崩溃。当间隔设置为比执行代码所花费的时间更短时,使用setInterval时常见错误。永远不要使用setInterval。

请记住Javascript不能同时做两件事。

处理资源监控加载的最佳方法是使用setTimeout。

var allLoaded = false;
var imgCount = 0;  // this counts the loaded images
// list of images to load
const imageURLS =["a.jpg","b.jpg","c.jpg","d.jpg","e.jpg"];
// array of images
var images = [];

const onImageLoad = function(){ imgCount += 1; } // onload event
// loads an image an puts it on the image array
const loadImage = function(url){
    images.push(new Image());
    images[images.length-1].src = url
    images[images.length-1].onload = onImageLoad;
}
const waitForLoaded = function(){
    if(imgCount === images.length){
        allLoaded = true;   // flag that the image have loaded
    }else{
        // display  the progress here
        ...

        setTimeout(waitForLoaded,100); // try again in 100ms
    }
}

// create the images and set the URLS
imageURLS.forEach(loadImage);

setTimeout(waitForLoaded,100);  // monitor the image loading

答案 2 :(得分:1)

使用Promise和异步功能,有一种不错的方法来等待所有图像加载完毕(没有回调,也没有加载计数的图像):

async function loadImages(imageUrlArray) {
    const promiseArray = []; // create an array for promises
    const imageArray = []; // array for the images

    for (let imageUrl of imageUrlArray) {
        let resolveFunction; // this function needs to be called to resolve the promise
        const imageLoadPromise = new Promise(resolve => {
            resolveFunction = resolve; // set the resolve function here
        });

        promiseArray.push(imageLoadPromise); // store the promise

        const img = new Image();
        // if you don't need to do anything when the image loads, then you can just write
        // img.onload = resolveFunction;

        img.onload = function() {
            // call the resolve function, indicating that the image has been loaded
            resolveFunction();

            // do stuff with the image if necessary
        };

        img.src = imageUrl;
        imageArray.push(img);
    }

    await Promise.all(promiseArray); // wait for all the images to be loaded
    // console.log("all images loaded");
    return imageArray;
}

或者您可以等待单个图像加载:

async function loadImage(imageUrl) {
    let resolveFunction;
    const imageLoadPromise = new Promise(resolve => {
        resolveFunction = resolve;
    });

    const img = new Image();
    img.onload = resolveFunction;
    img.src = imageUrl;

    await imageLoadPromise;
    // console.log("image loaded");
    return img;
}

您可以这样使用它(使用诺言链):

loadImages(myImages).then(images => {
    // the loaded images are in the images array
})

或在异步函数中:

const images = await loadImages(myImages);