views:

27

answers:

2

This might be a little hard to follow.

I've got a function inside an object:

f_openFRHandler:    function(input) {
            console.debug('f_openFRHandler');
            try{
                //throw 'foo';
                DragDrop.FileChanged(input);
                //foxyface.window.close();
            }
            catch(e){
                console.error(e);
                jQuery('#foxyface_open_errors').append('<div>Max local storage limit reached, unable to store new images in your browser. Please remove some images and try again.</div>');
            }
        },

inside the try block it calls:

this.FileChanged = function(input) {
            // FileUploadManager.addFileInput(input);
            console.debug(input);
            var files = input.files;
            for (var i = 0; i < files.length; i++) {
                var file = files[i];
                if (!file.type.match(/image.*/)) continue;

                var reader = new FileReader();
                reader.onload = (function(f, isLast) {
                    return function(e) {
                        if (files.length == 1) {
                            LocalStorageManager.addImage(f.name, e.target.result, false, true);
                            LocalStorageManager.loadCurrentImage();
                            //foxyface.window.close();
                        }
                        else {
                            FileUploadManager.addFileData(f, e.target.result); // add multiple files to list
                            if (isLast) setTimeout(function() { LocalStorageManager.loadCurrentImage() },100);
                        }
                    };
                })(file, i == files.length - 1);
                reader.readAsDataURL(file);
            }
            return true;

LocalStorageManager.addImage calls:

this.setItem = function(data){
                localStorage.setItem('ImageStore', $.json_encode(data));
        }

localStorage.setItem throws an error if too much local storage has been used. I want to catch that error in f_openFRHandler (first code sample), but it's being sent to the error console instead of the catch block. I tried the following code in my Firebug console to make sure I'm not crazy and it works as expected despite many levels of function nesting:

try{
    (function(){
        (function(){
            throw 'foo'
        })()
    })()
}
catch(e){
    console.debug(e)
}

Any ideas?

+1  A: 

I think the problem is that the error is happening later, after your f_openFRHandler function has completed. Note that the function where LocalStorageManager.addImage is being called is being set as the onload handler on the reader, not being called immediately. It gets called later, asynchronously, when the data is loaded.

You'll need to put your try..catch inside the anonymous function being created and assigned to that event, e.g.:

this.FileChanged = function(input) {
    // FileUploadManager.addFileInput(input);
    console.debug(input);
    var files = input.files;
    for (var i = 0; i < files.length; i++) {
        var file = files[i];
        if (!file.type.match(/image.*/)) continue;

        var reader = new FileReader();
        reader.onload = (function(f, isLast) {
            return function(e) {
                try {       // ADDED
                    if (files.length == 1) {
                        LocalStorageManager.addImage(f.name, e.target.result, false, true);
                        LocalStorageManager.loadCurrentImage();
                        //foxyface.window.close();
                    }
                    else {
                        FileUploadManager.addFileData(f, e.target.result); // add multiple files to list
                        if (isLast) setTimeout(function() { LocalStorageManager.loadCurrentImage() },100);
                    }
                }
                catch (err) { // ADDED
                    // YOUR HANDLING HERE
                }
            };
        })(file, i == files.length - 1);
        reader.readAsDataURL(file);
    }
    return true;
};

Your (excellent) test case makes the call synchronously, which is why the error is caught when you try it. This is a closer model to what's actually happening:

try{
    (function(){
        setTimeout(function(){  // Use setTimeout to model asynchronicity
            throw 'foo'
        }, 100);
    })()
}
catch(e){
    console.debug(e)
}
T.J. Crowder
+1  A: 
var reader = new FileReader();
                reader.onload = (function(f, isLast) {

Likely that's your problem right there - the FileReader probably calls onload asynchronously, at a time when your try/catch is no longer in scope. There may be a separate error handler function available on the FileReader interface, or you might need to move the try/catch into the anonymous function you're passing to onread().

Mark Bessey