I have an JavaScript extension that in short: upon user action, converts an image into a dataURI (and then does some processing)
Problem:
My issue is that using callbacks becomes unpleasant to deal with if more processing is required, for example, scaling, modifying, etc, where I use similar functions (load into a canvas, return result via callback) as they become nested and so on. It’d be better to keep things inline.
Question:
I’d like to use await image.decode()
, instead of image.onload => () {}
, but I’m afraid if I use await
, it’ll block the rest of the page, waiting for it to load.
I’ve read up on many an article and SO question, and I thought I understood asynchronous calls, but I’d just like to be certain.
Or should I even be using Promise
s?
Here’s what I’ve used so far –
function getImageDataURL(imageSource, callback){
let image = new Image();
let cans = document.createElement('canvas');
image.onload = function() {
// processing
cans.width = this.naturalWidth;
cans.height = this.naturalHeight;
cans.getContext('2d').drawImage(this, 0,0);
let q = 1
while (cans.toDataURL("image/webp", q).length > 7500 && q != 0) {
q -= 0.05; // Decreased quality increment size
}
callback(cans.toDataURL("image/webp", q));
cans.remove(); // Remove Element once complete
}
image.src = imageSource;
}
And I understand when the image load starts, it releases control of the execution to the rest of the page.
Which is good, as the user experience isn’t deteriorated.
If I did:
async function asyncGetImageDataUrl(source) {
...
image.src = source
await image.decode()
...
return dataURI
}
It appears to behave the same way in my testing, but is it? Or does it become blocking
Final question:
Would the result be any different, if I called result = await asyncGetImage(src)
?
Perhaps in an instance where I would want it to be blocking.
Added Context:
My usage might look like:
source = getImageSource(..)
if (source == foo) {
doThis()
}
getImageURL(source, (result) => {
if (result.length < max) {
store(result)
}
else {
moreImageProcessing(result, (processedResult) => {
...
}
}
}
And you can see how the nesting occurs with the initial pattern, and becomes messy.