I am trying to create an image compressor without any third-party library.
Here is my code(it will finally returns the blob of compressed image):
async function CompressImage(File, Quality, FileType) {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var img = new Image;
img.onload = function () {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
canvas.toBlob(function (blob) {
return blob;
}, FileType, Quality);
}
}
img.src = URL.createObjectURL(File);
}
It seems there is nothing wrong with my code while always returns an undefined value.
I found out maybe it is the asynchronous problem. The img.onload
and the canvas.toBlob
are asynchronous methods.
I think the promise
may help this while I don’t know how to order these methods run one by one and finally returns a value.
How can I solve this? Thank you.
Use a
Promise
instead ofasync
, in the end is the same but syntactically are not, in a Promise you get 2 functions as parameters (typically calledresolve
andreject
), these functions can be run inside any callback no problem, but in anasync
function becomes problematic because there’s no way toawait
for a function that receives a callback (because is not a Promise that you canawait
).TLDR;
async
functions do not play well executing functions that run callbacks, use a Promise directly so you can runresolve()
anywhere, even if is on a callback function.For example:
That should do the trick, look how I’m creating the promise to resolve it with the callback of
canvas.toBlob
, if you notice, the function is notasync
because is returning a Promise directly, but in your code, you can treat it just like an async function.Another way to do it with a little more updated syntax can be:
And should be the same.
I haven’t tested this but if is broken is pretty close.