-
-
Save asidko/9c7064027039411a11323eaf7d8ea2a4 to your computer and use it in GitHub Desktop.
| // Paste the following example to browser console | |
| // Comppreses string to GZIP. Retruns a Promise with Base64 string | |
| const compress = string => { | |
| const blobToBase64 = blob => new Promise((resolve, _) => { | |
| const reader = new FileReader(); | |
| reader.onloadend = () => resolve(reader.result.split(',')[1]); | |
| reader.readAsDataURL(blob); | |
| }); | |
| const byteArray = new TextEncoder().encode(string); | |
| const cs = new CompressionStream('gzip'); | |
| const writer = cs.writable.getWriter(); | |
| writer.write(byteArray); | |
| writer.close(); | |
| return new Response(cs.readable).blob().then(blobToBase64); | |
| }; | |
| // Decompresses base64 encoded GZIP string. Retruns a string with original text. | |
| const decompress = base64string => { | |
| const bytes = Uint8Array.from(atob(base64string), c => c.charCodeAt(0)); | |
| const cs = new DecompressionStream('gzip'); | |
| const writer = cs.writable.getWriter(); | |
| writer.write(bytes); | |
| writer.close(); | |
| return new Response(cs.readable).arrayBuffer().then(function (arrayBuffer) { | |
| return new TextDecoder().decode(arrayBuffer); | |
| }); | |
| } | |
| ///////////////////// | |
| // Checking | |
| ///////////////////// | |
| Promise.resolve("Hello GZIP!") | |
| .then(v => { | |
| console.log("Original value: %s", v); | |
| return v; | |
| }) | |
| .then(v => compress(v)) | |
| .then(v => { | |
| console.log("Compressed value: %s", v); | |
| return v; | |
| }) | |
| .then(v => decompress(v)) | |
| .then(v => console.log("Decomporessed value: %s", v)); |
Yeah ๐. There's a mixture of promise and classical code.
So we should wrap everything inside compress/decompress functions in Promise to make error follow it's .catch() flow, otherwise for current code you need both synchronous handling and promise handling:
try {
decompress("invalid$base64%#@").catch(e => console.log("Got a promise error when decompressing: " + e))
} catch (e) {
console.log("Got an synchronous error: " + e);
}
Result:
Got an error: InvalidCharacterError: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.
So, it's better to wrap a whole function in Promise and move try-catch block there
const decompress = (base64string) => {
return new Promise((resolve, reject) => {
try {
const bytes = Uint8Array.from(atob(base64string), c => c.charCodeAt(0));
const cs = new DecompressionStream('gzip');
const writer = cs.writable.getWriter();
writer.write(bytes)
.then(() => writer.close())
.then(() => new Response(cs.readable).arrayBuffer())
.then(arrayBuffer => resolve(new TextDecoder().decode(arrayBuffer)))
.catch(reject); // Catch any errors in the promise chain
} catch (error) {
reject(error); // Catch any synchronous errors
}
});
};
// Trying it
decompress("invalid$base64%#@").catch(e => console.log("Got a promise error when decompressing: " + e))
// Result: just .catch() is enough now to handle all errors
Got a promise error when decompressing: InvalidCharacterError: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.
Apologies for late re-reply. I just saw your answer after going thru my bookmarks.
I tried your codes and I don't know how to save the result into a var. Granted I'm still grasping on this whole Promise technique.
Anyway, this is the code that I've been using since I asked that question. It catches the error, but somehow the error is still on the console claiming that it's still uncatched. I don't know why this code works, but it works. Maybe you want to check it out. The error message is in writer.closed as far as I understand.
async function decomp(str,mode="gzip"){
// Using Node Buffer for encoder
str = Buffer.from(str, "base64")
const cs = new DecompressionStream(mode)
const writer = cs.writable.getWriter()
writer.write(str)
writer.close()
return await new Response(cs.readable).arrayBuffer()
.then(
// Resolve Function
arr=>(Buffer.from(arr)).toString("utf8"),
// Reject Function
async _=>{throw new Error(await Promise.reject(await writer.closed))}
)
}
let string = [
// "These strings were compressed!" compressed with gzip and base64 encoder
`H4sIAAAAAAAACgvJSC1OVSguKcrMSy9WKE8tSlVIzs8tKEotLk5NUQQAfREzrR4AAAA`,
// Change capital R near the end
`H4sIAAAAAAAACgvJSC1OVSguKcrMSy9WKE8tSlVIzs8tKEotLk5NUQQAfREzrr4AAAA`,
// Change 1 char at the end
`H4sIAAAAAAAACgvJSC1OVSguKcrMSy9WKE8tSlVIzs8tKEotLk5NUQQAfREzrR4AAAx`,
// Add 1 char at the end
`H4sIAAAAAAAACgvJSC1OVSguKcrMSy9WKE8tSlVIzs8tKEotLk5NUQQAfREzrR4AAAAx`,
],
result = []
console.clear()
for(let item of string){
try{
result.push(
"Succesfully decompressing!\n\n" + "String Result : "+ (await decomp(item))
)
}
catch(err){
result.push("Failed to decompress!\n\n"+ err.name +" : "+ err.message)
}
}
console.log(result.join("\n\n=====================================================================\n\n"))Also an important question, is there a notification page somewhere in github? I just saw your reply. But I already subscribe to this post / gist. There must be notification somewhere, right?
Cheers
Thanks @asidko I was trying to roll my own version of this but ran into an error from the Response: "TypeError: Failed to fetch". I believe it was something to do with my approach to base64 encoding. Your implementation worked a treat ๐
How do you catch the error?
I tried to decompress random Buffer bytes and got an error thrown
Uncaught (in promise) TypeError : The compress data was not valid. Invalid block data.I tried to catch it with
.catch(err=>{console.log(err)})but failed. Only gotTypeError : Failed to fetch.I've been reading about async function and
Promise, but still a dead end. Sorry if the question is too stupid or has an obvious answer.