javascriptasynchronousjszip

Check array after async task finishes


Today I'm having an issue with async task while using JSZIP. I want to check the array content after the async task executed by JSZip ends.

I have a zip which contains one XML file which I read and get a specific node to store them in another list to later do some stuffs. Well, my issue is that the checking array is called before the XML file is read and, as it is executed before XML file is read, array is empty.

I tried some ways to make it work, but, without success yet.

fileElement.addEventListener('change', (e) => {
    try {
        var zip = new JSZip();
        zip.loadAsync( fileElement.files[0])
        .then(function(zip) {
            let xmlfiles = []
            const _ziptask = async () => {for(let [filename, file] of Object.entries(zip.files)) {
                if (filename.includes("file.xml")) {
                    file.async("string").then(function (data) {
                        let xmlDoc = new DOMParser().parseFromString(data,"text/xml");
                        let metaInputs = [...xmlDoc.querySelectorAll("file")];
                        xmlfiles = metaInputs.filter(_node => null != _node.getAttribute('src'));
                        console.log("FILE.XML LOOP ENDED")
                    });             
                }
            }}
            async () => {
                await _ziptask().then(() => {
                    console.log("CHECKING FILE.XML ARRAY ")
                    console.log(xmlfiles)
                })
            }
        }, function() {console.error("ERROR: NOT ZIP FILE")}); 
    } catch (error) {
        restoreFileInput("Something went wrong, try it again later")
    }
});

Solution

  • Well, basically after testing different things, I reached the goal by using an array of promises and using Promise.all, which basically check that all the promises were resolved successfully.

    Its curious that where I read this, the promises are stored in a const declaration instead var or let.

    Anyway, if someone want to see the result:

    fileElement.addEventListener('change', (e) => {
        try {
            var zip = new JSZip();
            zip.loadAsync( fileElement.files[0])
            .then(function(zip) {
                let xmlfiles = []
                const promises = [];
                for(let [filename, file] of Object.entries(zip.files)) {
                    if (filename.includes("file.xml")) {
                        promises.push(file.async("string").then(function (data) {
                            let xmlDoc = new DOMParser().parseFromString(data,"text/xml");
                            let metaInputs = [...xmlDoc.querySelectorAll("file")];
                            xmlfiles = metaInputs.filter(_node => null != _node.getAttribute('src'));
                            console.log("FILE.XML LOOP ENDED")
                        }));             
                    }
                }
                Promise.all(promises).then(function () {
                    console.log("CHECKING FILE.XML ARRAY ")
                    console.log(xmlfiles)
                  });
            }, function() {console.error("ERROR: NOT ZIP FILE")}); 
        } catch (error) {
            restoreFileInput("Something went wrong, try it again later")
        }
    });
    

    Thanks for the help to the guys who commented previously. Best regards.