1

I am developing a flash card web page and I want to know when preloaded images have loaded or experienced an error. Once I have the status for each image I will take some action.

I am basing my code on the stackoverflow post Wait for image to be loaded before going on

function loadSprite(src) {
    var deferred = $.Deferred();
    var sprite = new Image();
    sprite.onload = function() {
        deferred.resolve();
    };
    sprite.src = src;
    return deferred.promise();
}

and the function loading the sprites

var loaders = [];
loaders.push(loadSprite('1.png'));
loaders.push(loadSprite('2.png'));
loaders.push(loadSprite('3.png'));
$.when.apply(null, loaders).done(function() {
// callback when everything was loaded
});

I have modified the loadSprite resolve to return a status result:

deferred.resolve("STATUS RESULT");

and the when

$.when.apply(null, loaders).done(function("STATUS RESULT") {
  // callback when everything was loaded
  //Do something with "STATUS RESULT"
});

The problem is that I can not separate out the "STATUS RESULT" for each call of loaders.push(loadSprite(file to load)); That is I only get one variable back not one for each call of loadSprite

I did not expect my above code to work, it is more of a demonstration to myself that I can pass something back.

I am unable to work this out, all assistance gratefully accepted. Thank you,

Community
  • 1
  • 1
user1558796
  • 293
  • 4
  • 19

2 Answers2

1

Actually, it works as expected. You can tune your creator method a little, like

function loadSprite( src ) {
    return $.Deferred(function( promise ) {
        var sprite = new Image();

        sprite.onload = promise.resolve.bind( null, "status result" );
        sprite.src = src;
    }).promise();
}

Now, when you push some promise objects into an array and apply .when() on that

loaders.push(loadSprite('1.png'));
loaders.push(loadSprite('2.png'));
loaders.push(loadSprite('3.png'));

each status result, will be listed in the arguments object from the .done() handler. So

$.when.apply(null, loaders).done(function() {
    console.log( arguments[ 0 ] ); // status result
    console.log( arguments[ 1 ] ); // status result
    // etc
});

Also, keep in mind that the .done handler of .when(), will only fire if all promise objects where resolved successfully.

That in turn means, if one of your images could not get loaded for some reason, its promise will never reach resolved state and therefore, your .when() handler will never fire.

jAndy
  • 231,737
  • 57
  • 305
  • 359
  • Thank you jAndy. I had experienced an error situation as you described when my internet connection was disrupted when images were preloading. How about using (is there a problem with two resolves in the one functon) take 1 for no error with 0 for error and with the code: `sprite.onload = promise.resolve.bind( null, 1);` and `sprite.onerror = promise.resolve.bind( null, 0);` I will then process the results for a file by file basis. Thank you again jAndy. – user1558796 Feb 26 '13 at 12:39
  • @user1558796: yeah, you can do that of course. if you wish to *manually* process the outcome of those loading states. On the other hand, you can also invoke `.fail()` on the `.when()` call to catch errors. But doing that, it still would not execute the `.done()` handler in the case of an error. So its probably a good idea to `.resolve()` the promise either way and pass in different states. – jAndy Feb 26 '13 at 12:49
  • Thank you jAndy. Apologies for only coming back to you now, I have just now for the first time had a chance to work with your solution. if I use `sprite.onload = promise.resolve.bind( null, 1 );` to return 1 for success when I `console.log( arguments[..] );` I get **1,[object Event]**. What do I have to do to remove _,[object Event]_ so that I can use the numerical response? Many thanks for your kind assistance – user1558796 Mar 03 '13 at 13:02
  • jAndy, I have figured it out, each element of `arguments[i]` is an array of length 2, so `arguments[i][0]` will return the numerical result that I am looking for having set it in `promise.resolve.bind( null, X);` where X is the numerical result. Tell me this, is the order of the values in the arguments array the same ordering as in the loaders array? That is from the example above loaders[2] refers to 3.png and arguments[2] refers to the response to 3.png? Many thanks – user1558796 Mar 03 '13 at 20:34
  • jAndy, Bad news for me, your solution does not work on an iPhone but it does on my laptop with Firefox and Internet Explorer. I am going to put together a simple test case with plenty of console.log outputs and I will post my findings if you would be so good to look at them. The code that I provided with this thread opener seems to work on my iPhone but of course I do not have the reporting of the status for each file. Characters in this comment section How should I post the code and results for my simple test case? Should I post it as an answer to my question? Many thanks – user1558796 Mar 04 '13 at 14:41
  • @user1558796: for the order in the `arguments` *array-like-object* within the *success* and *fail* handlers, those will have the same order as the order of promises which got passed into `.when()`. So short answer, yes, it will be the same order. As for the iPhone, sounds wierd because iPhones run webkit browsers by default, which should have no trouble with all this little javascript. A good place to showoff your code is http://www.jsfiddle.net or http://www.pastebin.com – jAndy Mar 04 '13 at 15:21
  • Thank you jAndy, I will post code to one of those sites of a demo that works in Firefox but not iPhone, probably not until Friday evening. – user1558796 Mar 07 '13 at 08:31
  • jAndy, I have pasted the code that does not work for me to [link](http://www.ipaste.eu/view.php?id=2585) This works as intended on a desktop but fails on an iPhone, specifically in the function loadSprite the line report("In loadSprite, After: sprite.onload = promise.resolve.bind( null, OK )") never gets called. Many thanks. – user1558796 Mar 15 '13 at 16:13
  • Hi @jAndy have you had any thoughts about the demo code and the issue on an iPhone? Many thanks. – user1558796 Mar 30 '13 at 20:23
0
function function_1()
{
    // Async part example
    var call = $.ajax({
        //....
    });
    call.then(handelSuccess);

    var df = $.Deferred();
    function handelSuccess(data, status, jqXHR) {
        //some code
        df.resolve(data);
    }

    return df;
}

this is one way to how to receive that data:

function main()
{
    var df = function_1();
    $.when(df).done(function () {
        df.promise().then(function (data) {
            console.log(data);
        });
    });
}
Adel Mourad
  • 1,351
  • 16
  • 13