图像加载时间和onload函数调用

时间:2015-06-17 15:05:40

标签: javascript image performance

下面的列表是Udacity面向对象的javascript课程最终项目的蛙游戏的一部分。它由Udacity给出,以下代码的目的是构建一个简单的图像加载缓存。我的问题是在列表之后。 Git:https://github.com/udacity/frontend-nanodegree-arcade-game

(function() {
    var resourceCache = {};
    var loading = [];
    var readyCallbacks = [];
    function load(urlOrArr) {
        if(urlOrArr instanceof Array) {
            urlOrArr.forEach(function(url) {
                _load(url);
            });
        } else {
            _load(urlOrArr);
        }
    }
    function _load(url) {
        if(resourceCache[url]) {
            return resourceCache[url];
        } else {
            var img = new Image();
            img.onload = function() {
                resourceCache[url] = img;
                if(isReady()) {
                    readyCallbacks.forEach(function(func) { func(); });
                }
            };
            resourceCache[url] = false;
            img.src = url;
        }
    }
    function get(url) {
        return resourceCache[url];
    }
    function isReady() {
        var ready = true;
        for(var k in resourceCache) {
            if(resourceCache.hasOwnProperty(k) &&
               !resourceCache[k]) {
                ready = false;
            }
        }
        return ready;
    }
    function onReady(func) {
        readyCallbacks.push(func);
    }
    window.Resources = {
        load: load,
        get: get,
        onReady: onReady,
        isReady: isReady
    };
})(); 

Resources.load([
    'images/stone-block.png',
    'images/water-block.png',
    'images/grass-block.png',
    'images/enemy-bug.png',
    'images/char-boy.png'
]);
Resources.onReady(init);//init function is to start the game

我的问题是关于这一行

img.src = url

我认为在此行之后,图像将立即加载,img.onload将立即被触发。我想如果是这样的话,那么:

在img.onload()函数中,由于此时resourceCache中只有一个属性并且已设置为' img',isReady()调用将返回true,而readyCallbacks将返回叫做。但是,由于.onReady()函数尚未执行(程序仍在Resources.load()函数中),此时readyCallbacks中没有任何内容,因此程序将不执行任何操作,但稍后,因为img.onload已被触发,它不会被再次触发,因此在执行Resources.onReady()并将init()函数插入readyCallbacks之后,它将不会被调用,因此游戏不会被激活被启动。

我正在阅读代码,当我到达这里时我无法理解。在我逐步运行代码之后,我发现实际上需要花费时间来加载图像,即使它们都是本地的。使用performance.now(),我发现它需要加载大约0.5ms的图片,然后调用_load()的for循环已经完成,并且第二个和第三个resourceCache的属性已经设置为false,所以isReady()不会评估为true,代码将正常运行。如果只加载一个图像,那么在加载图像之前,将调用.onReady()(在Resource.load()之后)并且init()将被插入到readyCallback中,并且代码也会奏效。

如果对我的上述分析没有任何问题,那么有一件事我还是不明白:我们真的可以依赖这个图像加载时间比其他代码更多吗?执行时间处理时间?如果图像非常小并且在rescourceCache的另一个属性被设置为' false'之前触发img.onload会怎么样?还是设置了readyCallback?如果是这样,代码就不会起作用。

当我进一步思考时,我无法理解为什么要提出

    if (isReady()) {
        readyCallbacks.forEach(function (func) {
            func();
        });
    }
img.onload()函数中的

,当我们要加载多个图像时,它会多次执行。我们可以把它放在.load()调用之后吗?毕竟,其目的是检查是否已加载所有图像。

1 个答案:

答案 0 :(得分:1)

img.onload回调放在执行队列中,最早不执行,直到其余代码运行完毕。

isReady函数被多次调用,因为如果所有图像都已完成下载,该函数将仅返回true。它需要在每个图像之后运行,因为无法知道哪个图像将是最后一个完成加载的图像,从而触发回调。