Javascript在另一个函数中使用返回值

时间:2014-08-15 13:12:13

标签: javascript jquery callback return-value deferred

我想要实现的是使用"预览文件" 功能的返回值作为" readfiles" 功能。但这需要在" image.onload" 部分执行之后,因为我需要returnThis设置为true。 我已经在谷歌和Stackoverflow上研究了一些关于这个问题和一般回调/延期对象的事情,但我无法理解如何在这种情况下应用它。

我的图片上传部分中有以下星座:

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                                                                                                    
    }                                                                                                                                    
}                                                                                                       

3 个答案:

答案 0 :(得分:2)

我会选择这样的东西

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
}

答案 1 :(得分:1)

由于previewfile()依赖于异步活动,因此它本身就是异步的。因此,它无法可靠地返回值,但它可以返回一个承诺。

正如其他人所指出的,可以编写previewfile()来接受回调,这将避免需要承诺。但是,如果你想要一个承诺解决方案,这里有一个(当然不是唯一的)。

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()现在可以编写如下:

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
    });
}

基于承诺的解决方案的好处可能不是处理成功而是管理错误。请注意单个处理程序如何报告几种不同类型的错误。

答案 2 :(得分:1)

在FelixKling和kallehj的帮助下,这是一个有效的解决方案(带回调):

// 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                                                                                                    
        }                                                                                                                                    
    }        
});