Javascript Loop doesn't wait for Firebase to complete uploading multiple files

心已入冬 提交于 2021-01-28 14:29:50

问题


I'm trying to upload multiple files and then execute some code after all the files are uploaded but my loop doesn't wait until each upload completes.

Iterating files:

//files is an array of local files from a <input type="file">
for (var i = 0, f; f = files[i]; i++) {
     var imageFile = files[i];
     var response = uploadImageAsPromise(imageFile);
}
//after completing all uploads, execute some code here
console.log("Finished uploading all files");

Upload function:

function uploadImageAsPromise(imageFile) {
    var image_id = new Date().valueOf();
    var storageRef = firebase.storage().ref().child(image_id + "");
    return new Promise(function (resolve, reject) {
        //Upload file
        var task = storageRef.put(imageFile);

        //Update progress bar
        task.on('state_changed',
            function progress(snapshot) {
                var percentage = snapshot.bytesTransferred / snapshot.totalBytes * 100;
            },
            function error(err) {
                console.log(err);
            },
            function complete() {
                task.snapshot.ref.getDownloadURL().then(function (downloadURL) {
                    var picture = downloadURL;
                    console.log("Finished uploading file: " + image_id);
                });
            }
        );
    });
}

However, my 1st console log gets executed even before all files are uploaded. How do I made it wait until everything is done?


回答1:


The first problem is your uploadImageAsPromise function. It never actually resolves the promise it creates, so anything that is waiting on the result will wait forever.

This should presumably work:

function uploadImageAsPromise(imageFile) {
    var image_id = new Date().valueOf();
    var storageRef = firebase.storage().ref().child(image_id + "");
    return new Promise(function (resolve, reject) {
        //Upload file
        var task = storageRef.put(imageFile);

        //Update progress bar
        task.on('state_changed',
            function progress(snapshot) { },
            function error(err) { reject(err); },
            function complete() { resolve(task); }
        );
    }).then(function (task) {
        return task.snapshot.ref.getDownloadURL();
    }).then(function (downloadURL) {
        console.log("Finished uploading file: " + image_id);

        return downloadURL;
    });
}

You're not doing anything to wait until the promises complete, so naturally, the next code will continue executing.

To upload the files in parallel and wait until they're done

With async/await (if your execution environment supports it):

async function uploadFiles(files) {
   await Promise.all(files.map(uploadImageAsPromise));
}


async function someOuterFunction(files) {
   await uploadFiles(files);

   console.log('All done!');
}

someOuterFunction(files);

Without async/await:

Promise.all(files.map(uploadImageAsPromise))
    .then(function () {
        console.log('All done!');
    });

To upload the files sequentially and wait until they're done

With async/await (if your execution environment supports it):

async function uploadFiles(files) {
    for (let file of files) {
        await uploadImageAsPromise(file);
    }
}

async someOuterFunction(files) {
     await uploadFiles(files);

     console.log('All done!');
}

someOuterFunction(files);

Without async/await:

files
    .reduce(function (acc, file) {
        return acc.then(function () { return uploadImageAsPromise(file); });
    }, Promise.resolve())
    .then(function () { console.log('All done!'); });



回答2:


You need to wait for all of the promises to resolve. You can do this concurrently using Promise.all (docs here).

var promises = [];

for (var i = 0, f; f = files[i]; i++) {
     var imageFile = files[i];
     promises.push(uploadImageAsPromise(imageFile));
}

Promise.all(promises).then(function(values) {
    //after completing all uploads, execute some code here
    console.log("Finished uploading all files", values);
}).catch(function(error) {
    console.log("One of the promises rejected.", error);
});


来源:https://stackoverflow.com/questions/53809980/javascript-loop-doesnt-wait-for-firebase-to-complete-uploading-multiple-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!