Wesley Smith
Wesley Smith

Reputation: 19571

Dont resolve promise until after images load

The below is supposed:

My problem:

How can I change this promise so that it does not resolve until all the images have been loaded and converted?

 function accountCreation(){
    $('#container').hide(); // hide the display while we save the info as it will take a few seconds, you should do a loading bar or something here instead
    var user = Parse.User.current(); // get the currently logged in user object

    // loop through each image element
    var promises = $('.images').map(function(index, element) {
          var src = $(element).attr('src');
          var canvas = document.createElement('CANVAS');
          var ctx = canvas.getContext('2d');
          var img = new Image;
          img.crossOrigin = 'Anonymous';
          img.onload = function(){
              canvas.height = img.height;
              canvas.width = img.width;
              ctx.drawImage(img,0,0);
              var base64Img = canvas.toDataURL('image/png');
              // Clean up
              canvas = null; 
              return base64Img;
          };
          img.src = element.src;
    });
    $.when.apply($, promises).then(function() {
        // arguments[0][0] is first result
        // arguments[1][0] is second result and so on
        for (var i = 0; i < arguments.length; i++) {
            var file = new Parse.File("photo.jpg", { base64: arguments[i]}); // this part actually saves the image file to parse
            user.set("image" + i, file); // set this image to the corosponding column on our object 
        }
        // save the user object
        user.save(null,{
          success: function(user) { 
                  $('#message').html('Profile Updated!');
                  $('#container').show(); // show the screen again, you should just remove your loading bar now if you used one
          },
          error: function(user, error) {
                  console.log('Failed to create new object, with error code: ' + error.message);
          }
        });
    });
 }

Upvotes: 0

Views: 2225

Answers (1)

Guffa
Guffa

Reputation: 700622

Your array of promises just contains undefined values, as the callback function doesn't return anything. As there are no Deferred objects in the array, the when method doesn't have anything to wait for, so it runs the then callback right away.

Create a Deferred object to return, and resolve it when the image is loaded:

var promises = $('.images').map(function(index, element) {
    // created a Deferred object to return
    var deferred = $.Deferred();
    var src = $(element).attr('src');
    var canvas = document.createElement('CANVAS');
    var ctx = canvas.getContext('2d');
    var img = new Image;
    img.crossOrigin = 'Anonymous';
    img.onload = function(){
        canvas.height = img.height;
        canvas.width = img.width;
        ctx.drawImage(img,0,0);
        var base64Img = canvas.toDataURL('image/png');
        // Clean up
        canvas = null;
        // Resolve the Deferred object when image is ready
        deferred.resolve(base64Img);
    };
    img.src = element.src;
    // return the Deferred object so that it ends up in the array
    return deferred;
});

Upvotes: 1

Related Questions