2

I'm trying to upload an array of files using FileReader which are base64 encoded and stored in an array for further processing. I'm struggling to understand the pattern I need to create in order to ensure all files have been uploaded because I have to wait for the onload event handler to fire. For example;

If I pass an array of files to the following function it will resolve the promise before the files are actually uploaded.

localUploads( event ) : any {

    var response = [];

    return new Promise( function(resolve, reject) {

        //Retrieve all the files from the FileList object
        var files = event.target.files;
        var response = [];

        if (files) {

            for (var i=0, f; f=files[i]; i++) {

                var r = new FileReader();

                r.onload = (function(f) {

                    return function(e) {

                        let contents = e.target['result'];

                        let file = {
                            name: f.name,
                            asset: contents,
                            private: false
                        };

                        console.log('we are pushing into the array');
                        response.push( file );
                    };

                })(f);


            }   
            resolve( response );
        }

        r.readAsText(f);
    });
}

Can anybody please advise a novice?

Many thanks.

1 Answer 1

1

It's all about resolving the promise at the right time. Currently you resolve it when the loop is done, but that doesn't mean that all the items have been processed. I haven't used FileReader, but you should be able to do something like this:

localUploads( event ) : any {

    var response = [];

    return new Promise(function(resolve, reject) {

        //Retrieve all the files from the FileList object
        var files = event.target.files;
        var response = [];

        if (files) {

            for (var i=0, f; f=files[i]; i++) {

                var r = new FileReader();
                r.onload = function(e) { // Possible clean-up?
                    let contents = e.target['result'];

                    let file = {
                        name: f.name,
                        asset: contents,
                        private: false
                    };

                    console.log('we are pushing into the array');
                    response.push( file );
                    if(response.length == files.length)
                    {
                        // Everything is done. Resolve the promise.
                        resolve( response );
                    }
                };
                // Moved here to be able to access r and f variables
                r.readAsText(f);
            }   
        }
    });
}

Or the old way using $q.

    var response = [];
    var dfd = $q.defer();

    //Retrieve all the files from the FileList object
    var files = event.target.files;
    var response = [];

    if (files) {
        for (var i=0, f; f=files[i]; i++) {
            var r = new FileReader();
            r.onload = function(e) { // Possible clean-up?
                let contents = e.target['result'];

                let file = {
                    name: f.name,
                    asset: contents,
                    private: false
                };

                console.log('we are pushing into the array');
                response.push( file );
                if(response.length == files.length)
                {
                    // Everything is done. Resolve the promise.
                    dfd.resolve(response);
                }
            };
            // Moved here to be able to access r and f variables
            r.readAsText(f);
        }   
    }
    else {
        // Possible resolve promise here to?
    }
    return dfd.promise;

Note that you might also want to handle the possible errors. If one of the files isn't completed sucessfully the promise will never be resolved.

You might need to resolve the promise in onloadend instead of onload. I really cannot figure it out from the docs.

var r = new FileReader();
r.onload = function(e) {
    if(response.length == files.length)
    {
        // Everything is done. Resolve the promise.
        dfd.resolve(response);
    }
}
Sign up to request clarification or add additional context in comments.

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.