jszip
jszip copied to clipboard
Can file extraction work in SYNC mode, instead of async?
I need to extract files from a ZIP file in a loop and after each extraction some GUI elements must be changed before the next file is being extracted. Can this be done in principle with jszip? The 'async' working of jszip currently prevents this and messes with the correct sequence of the code.
Is there a 'sync' way to do this?:
myzip.file(zipEntry.name).async("string").then(function(content) { ...
Note: no lecture needed why the GUI interaction is happening all. I just need to implement a 'batch' mode into a complex tool which was developed originally to work with single files and massive user interaction only. There is currently no capacity in the company to completely re-design the whole thing. The un-zip loop just needs to wrap around code which sets some GUI elements whose values are used in the following steps, so a strict sequence MUST be kept.
I just tested this JSZip-sync fork: https://github.com/ericvergnaud/jszip
But when I simply wrap my extraction loop into zip.sync(function() {
...
like in the example it thows me a external.Promise.reject is not a function
error on lin 3670 in jszip.js
Does anybody know whether this 'sync' version of JSZip is supposed to work at all in a scenario like mine - meaning: sync-ing a loop where extractions and following processing of files MUST be done in a strict sequence?
I'd like to see a 100% complete list of possible use cases for this library from anyone who offhandedly dismisses the value of being able to use it synchronously 🙄
My solution was defining several other async functions and forcing them all to wait for each other. The trick here is a self-executing function that must complete before moving onto the next file in the processing loop.
JSZip.loadAsync(myzip).then(
process_zip,
e => console.log(`error reading ${myzip.name}: ${e.message}`)
).then(...);
async function process_zip(zip) {
const zip_array = [];
zip.forEach((path, entry) => zip_array.push([path, entry]));
for (let i of zip_array) {
await (async (item) => {
await each_entry(new_zips, item[1]);
})(i);
}
return zip;
}
async function each_entry(entry) {
let file_string;
await entry.async('string').then((c) => {
file_string = c;
});
await do_something_else_before_the_next_one_starts(entry, file_string);
}
Alternatively consider fflate
for better performance and synchronous APIs.
I'm trying to use jszip to extract files on a fly within a callback which happens from wasm module, but without sync methods, it's pointless. The wasm module can't just wait for the results from async method just to read file file, it just expect the right results on function return.
I've tried to do something like this (where this.myfiles
is the list of files from the zip file preloaded via zip.forEach
):
readFile = (path, cwd) => {
path = path[0] == "/" ? path.substring(1) : path;
if (this.state.ready && this.myfiles[path]) {
let dataResult = null;
let dataReady = false;
let promise = (async () => {
this.myfiles[path]
.async("string")
.then(function (data) {
dataReady = true;
dataResult = data;
return data;
})
.catch((error) => {
dataReady = true;
dataResult = "";
return "";
});
})();
}
return "";
};
but it just doesn't work.
Ideally there should be a sync method to decompress file from data property (related: GH-818).
Related: GH-281.