0

I 'm currently having a hard time figuring out why an object is once defined and on the next line it is not.

In my code, I'm declaring a promise with a for loop inside, that loops through a couple of file inputs and checks the files(images) dimension. Once all inputs are processed the promise is resolved and the then method fires.

for(var i = 0; i < $('.apk-wrapper .mandatoryImg').length; i++){
        if ($('.apk-wrapper .mandatoryImg')[i].value){
            var id = $($('.apk-wrapper .mandatoryImg')[i]).attr('id');
            var imageProcessing = new Promise(function(resolve,reject){
                if(id == 'game_icon'){
                    imageProcessor($('.apk-wrapper .mandatoryImg')[i],512,512)
                }
                else if(id == 'ingame1'){
                    imageProcessor($('.apk-wrapper .mandatoryImg')[i],720,1280)
                }
                 ...
                else{
                  error = true;
                  reject()
                }
               if(i == $('.apk-wrapper .mandatoryImg').length - 1){
                   resolve(images)
               }
          }
    }).then(function(images){
        console.log(images)
        // console.log(images.length)
    })

If I now log the array of processed images I get the correct Object with indexes.

Array[0]
0:File
1:File
2:File
3:File
4:File
5:File
length:6

When I try to get the length of that object, I tried multiple methods(.length, while hasOwnProperty, for keys in x), I always get back 0.

Pascal
  • 23
  • 8
  • *When* do you try to get the length of *what* object? – Dave Newton Dec 16 '16 at 11:39
  • On the same line I log the object itself. I just removed it. – Pascal Dec 16 '16 at 11:42
  • I just removed it for convenience. The object is initialized globally and the function imageProcessor(element,width,height) pushes the processed file to that object. – Pascal Dec 16 '16 at 11:46
  • 1
    At the very least you're going to have a problem because `i` isn't bound to the current iteration count with the `Promise` callback. – Alnitak Dec 16 '16 at 11:51
  • So I need to wrap the loop into the promise? Sorry, I'm pretty new to async programming. – Pascal Dec 16 '16 at 11:55
  • Yeah, there's a lot of fail here - give me a couple of minutes – Alnitak Dec 16 '16 at 11:55
  • Is there a little blue `i` next to the object being logged? Could well be that you're seeing it being re-evaluated when you expand it, and at the time of being logged it _did_ have a length of 0. – James Thorpe Dec 16 '16 at 11:56
  • @JamesThorpe: Yap, there is a blue i "Value was evaluated just now" – Pascal Dec 16 '16 at 11:59
  • 1
    @Pascal I can't tell which parts of your code are async such that you actually need to use promises. Is it the calls to `imageProcessor` ? – Alnitak Dec 16 '16 at 12:03
  • @Alnitak: Jap the function creates an image with FileReader to the width and height of input images. If they match the passed width and height values they are pushed into the images array/object – Pascal Dec 16 '16 at 12:06
  • 1
    It would be better if the `imageProcessor` function returned a Promise that resolves to the new `Image` object. – Alnitak Dec 16 '16 at 12:07
  • Please fix your indentation and provide syntactically valid code. I can *not* see that they're really in the same block. Nor why you are using promises at all. – Bergi Dec 16 '16 at 13:55
  • Btw, you seem to [get confused by the console](http://stackoverflow.com/q/4057440/1048572) – Bergi Dec 16 '16 at 13:56

1 Answers1

0

To get a Promise that's resolved only when all of the files are processed, try this (assuming that imageProcessor itself returns a Promise):

var promises = $('.apk-wrapper .mandatoryImg').map(function(i, el) {
    var id = el.id;
    if (id === 'game_icon') {
        return imageProcessor(el, 512, 512);
    } else if (id === 'ingame1') {
        return imageProcessor(el, 720,1280)
    } else if {
         ...
    } else {
         return Promise.reject();
    }
}).get();   

The $(...).map(...).get() chain obtains an array of Promises, one for each element in the jQuery collection.

You can then wait for all those Promises to be resolved before proceeding:

Promise.all(promises).then(function(images) {
     ...
});
Alnitak
  • 334,560
  • 70
  • 407
  • 495