5

What I want to achive is using the return value of the "previewfile" function as an execution indicator for the "readfiles" function. But this needs to be after the "image.onload" part has been executed, since there I need returnThis to be set to true. I've researched several things on Google and Stackoverflow concerning this problem and callbacks / deferred objects in general, but I cannot wrap my head around how to applicate that in this situation.

I have the following constellation in my Image uploading section:

function previewfile(file, tests, acceptedTypes, holder) {
    var returnThis = false;                                                                               
    if (tests.filereader === true && acceptedTypes[file.type] === true) {                                                                
        var reader = new FileReader();                                                                                                   
        reader.onload = function (event) {                                                                                               
            var image = new Image();                                                                                
            image.onload = function() {                                                                                                  
                var testimage = new Image();                                                                                             
                testimage.src = $(this).attr('src');                                                                                     
                var widthOfImage = testimage.width;                                                                                      
                var heightOfImage = testimage.height;                                                                                    
                if (!checkImageDimensions(widthOfImage, heightOfImage)) {
                    // do stuff                                                  
                } else {
                    returnThis = true;                                                                                           
                }                                                                                                                        
            };                                                                                                                           
            image.src = event.target.result;                                                                                             
            holder.appendChild(image);                                                                                                   
        };                                                                                                                               
        reader.readAsDataURL(file);                                                                                                      
    }  else {                                                                                                                            
        // do other stuff                                                                                                              
    }                                                                                                                                    
    return returnThis;                                                                                                                   
}                                                                                                                                        
function readfiles(files, tests, acceptedTypes, holder, progress) {                                                                      
    var uploadNow = previewfile(files[0], tests, acceptedTypes, holder);                                                                   
    if (uploadNow === true) {                                                                                                               
        // do stuff                                                                                                          
        }                                                                                                                                
    } else {                                                                                                                             
        // do other stuff                                                                                                    
    }                                                                                                                                    
}                                                                                                       
8
  • What about simple callback? Commented Aug 15, 2014 at 13:15
  • 1
    There is nothing special about this situation. Make previewfile accept a function and call it when the image is available. Commented Aug 15, 2014 at 13:27
  • 1
    You have to call the callback from inside the onload handler and inside the else statement. Commented Aug 15, 2014 at 13:35
  • 1
    You put callback(returnThis); at the end of the image.onload function. At that moment the reader.onload function already executed. Commented Aug 15, 2014 at 13:40
  • 1
    @FelixKling Yeah I did that already, but because of another error (that I just found) it didn't work. You made me look closer again, thank you! Commented Aug 15, 2014 at 13:43

3 Answers 3

2

I would go with something like this

function readfiles(files, tests, acceptedTypes, holder, progress) {                                                                      
    previewfile(files[0], tests, acceptedTypes, holder, function(value){
        if (uploadNow === true){                                                                                                               
             // do stuff                                                                                                          
        }                                                                                                                                
        else {                                                                                                                             
            // do other stuff                                                                                                    
        } 
    });                                                                   

}

function previewfile(file, tests, acceptedTypes, holder, callback) {
    ...
    callback(returnValue); //instead of return
}
Sign up to request clarification or add additional context in comments.

1 Comment

Though this answer was helpful, it is not completely correct. I'd accept it, but my edit to correct it (so that it is actually working) was refused. So I cannot mark this as the accepted answer.
1

As previewfile() relies on asynchronous activity, it is itself effectively asynchronous. As such, it can't reliably return a value, but it can return a promise.

As others have pointed out, previewfile() can be written to accept a callback, which would avoid the need for a promise. However, if you want a promise solution, here is one (certainly not the only one).

function previewfile(file, tests, acceptedTypes, holder) {
    if(tests.filereader === true && acceptedTypes[file.type] === true) {
        var reader = new FileReader(),
            image;
        var promise_a = $.Deferred(function(dfrd) {
            reader.onload = function(event) {
                image.attr('src', event.target.result).appendTo(holder);
                dfrd.resolve();
            };
            reader.onerror = function() {
                dfrd.reject('fileReader error');
            };
        }).promise();
        var promise_b = $.Deferred(function(dfrd) {
            image = $("<img/>").on('load', function() {
                var widthOfImage = image.width;
                var heightOfImage = image.height;
                if (checkImageDimensions(widthOfImage, heightOfImage)) {
                    dfrd.resolve();
                } else {
                    //do stuff
                    dfrd.reject('image loaded but dimensions did not check out');
                }
            }).error(function() {
                dfrd.reject('image did not load');
            });
        }).promise();
        reader.readAsDataURL(file);
        return $.when(promise_a, promise_b);
    } else {
        // do other stuff
        // Also return a promise here, even if no async is involved.
    }
}

readfiles() can now be written as follows :

function readfiles(files, tests, acceptedTypes, holder, progress) {
    return previewfile(files[0], tests, acceptedTypes, holder).then(function() {
        // do stuff
    }).then(null, function(reason) {
        console.log(reason);// or display to the user in the DOM.
        // do other stuff
    });
}

The benefit of a promise-based solution is maybe not so much in handling success as managing errors. Note how a single handler reports several different types of error.

Comments

1

With the help of FelixKling and kallehj, this is the working solution (with callback):

// important
function previewfile(file, tests, acceptedTypes, holder, callback) {
    var returnThis = false;                                                                               
    if (tests.filereader === true && acceptedTypes[file.type] === true) {                                                                
        var reader = new FileReader();                                                                                                   
        reader.onload = function (event) {                                                                                               
            var image = new Image();                                                                                
            image.onload = function() {                                                                                                  
                var testimage = new Image();                                                                                             
                testimage.src = $(this).attr('src');                                                                                     
                var widthOfImage = testimage.width;                                                                                      
                var heightOfImage = testimage.height;                                                                                    
                if (!checkImageDimensions(widthOfImage, heightOfImage)) {
                    // do stuff                                                  
                } else {
                    returnThis = true;                                                                                           
                }
                callback(returnThis);             // important                                                                                                           
            };                                                                                                                           
            image.src = event.target.result;                                                                                             
            holder.appendChild(image);                                                                                                   
        };                                                                                                                               
        reader.readAsDataURL(file);                                                                                                      
    }  else {                                                                                                                            
        callback(returnThis);                    // important                                                                                         
    }                                                                                                                  
}                                                                                                                                        
function readfiles(files, tests, acceptedTypes, holder, progress) {
    // important                                                                      
    previewfile(files[0], tests, acceptedTypes, holder, function (uploadNow) {
        if (uploadNow === true) {                                                                                                               
            // do stuff                                                                                                          
            }                                                                                                                                
        } else {                                                                                                                             
            // do other stuff                                                                                                    
        }                                                                                                                                    
    }        
});                                                                                               

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.