简体   繁体   English

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

[英]image loading time and onload function call

The list below is part of a frogger game from Udacity's object-oriented javascript course's final project. 下面的列表是Udacity的面向对象的javascript课程的最终项目中的frogger游戏的一部分。 It is given by Udacity, The purpose of following code is to build a simple image loading cache. 它由Udacity给出。以下代码的目的是建立一个简单的图像加载缓存。 My question is after the list. 我的问题在清单之后。 Git: https://github.com/udacity/frontend-nanodegree-arcade-game 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

My question is about this line 我的问题是关于这条线

img.src = url

I've thought that after this line, the image will be loaded immediately and the img.onload will be fired right away. 我以为在此行之后,图像将立即加载,并且img.onload将立即被触发。 I think If this was the case, then: 我认为如果是这种情况,那么:

Inside the img.onload() function, since there is only one property in resourceCache at this time and it has been set to 'img', the isReady() call will return true, and readyCallbacks will be called. 在img.onload()函数内部,由于此时resourceCache中只有一个属性,并且已将其设置为'img',因此isReady()调用将返回true,并且将调用readyCallbacks。 However, since the .onReady() function hasn't been executed(the program is still in the Resources.load() function), there is nothing in readyCallbacks at this time, so the program will do nothing, but later on, since img.onload has been fired, it will not be fired again, thus after Resources.onReady() is executed and the init() function is inserted into readyCallbacks, it will not be invoked, so the game won't be initiated. 但是,由于尚未执行.onReady()函数(程序仍在Resources.load()函数中),因此此时readyCallbacks中没有任何内容,因此该程序将不执行任何操作,但稍后,因为img.onload已被触发,不会再次被触发,因此在执行Resources.onReady()并将init()函数插入readyCallbacks之后,将不会调用它,因此不会启动游戏。

I was reading the code, when I got here I couldn't understand. 我正在阅读代码,当我到达这里时我听不懂。 After I run the code step by step, I find out that it actually takes time for the images to be loaded, even though they are all local. 逐步运行代码后,我发现加载图像实际上需要时间,即使它们都是本地的。 Using performance.now(), I found that it takes a picture about 0.5ms to be loaded, by then the for loop in which _load() is called has completed, and the 2nd and 3rd resourceCache's properties have been set to false, so isReady() won't evaluate to true, and the code will behave normally. 使用performance.now(),我发现要加载约0.5ms的图像,届时已完成调用_load()的for循环,并且将第二和第三resourceCache的属性设置为false,因此isReady()的计算结果不会为true,并且代码将正常运行。 And if there is only one image to load, then before the image is loaded, the .onReady() ( which is after Resource.load() ) will have been called and init() will have been inserted into readyCallback, and the code will work too. 并且如果仅要加载一个图像,则在加载图像之前,将调用.onReady()(位于Resource.load()之后),并将init()插入readyCallback中,并且代码也会工作。

If there is nothing wrong with the above analysis of mine, then there is one thing I still don't understand: can we really rely on this image loading time being more than other codes' execution time? 如果我的上述分析没有任何问题,那么我仍然不了解一件事:我们真的可以依靠这个图像加载时间超过其他代码的执行时间吗? what if the images are really small and img.onload fires before another property of rescourceCache is set to 'false' or the readyCallback has been set up? 如果图像真的很小并且img.onload在rescourceCache的另一个属性设置为'false'或readyCallback被设置之前触发了怎么办? If so the code won't work. 如果是这样,代码将无法正常工作。

When I think further, I can't understand why we have to put 当我进一步思考时,我不明白为什么我们必须

    if (isReady()) {
        readyCallbacks.forEach(function (func) {
            func();
        });
    }

in the img.onload() function, which makes it being executed multiple times when we are to load multiple images. 在img.onload()函数中,这使得它在我们要加载多个图像时被多次执行。 Can we just put it after the .load() call in the ? 我们可以将其放在.load()调用之后吗? After all, its purpose is to check if all the images have been loaded. 毕竟,它的目的是检查是否所有图像都已加载。

The img.onload callback is placed in the execution queue and not executed, at the earliest, until the rest of the code has run to completion. img.onload回调最早被放置在执行队列中,直到其余代码运行完毕为止才执行。

The isReady function is called multiple times because that function will only return true if all the images have finished downloading. 多次调用isReady函数,因为该函数仅在所有图像都已完成下载后才返回true It needs to be run after each image because there's no way to know which image will be the last one to finish loading and thereby trigger the callbacks. 它需要在每个映像之后运行,因为无法知道哪个映像将是最后一个完成加载并触发回调的映像。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM