Resize base64 image and get the return value out of the function in nodejs

async function imgResize(data){
// Convert base64 to buffer => <Buffer ff d8 ff db 00 43 00 ...
const buffer = Buffer.from(data, "base64");
Jimp.read(buffer, (err, res) => {
    if (err) throw new Error(err);
    console.log("Original image size: "+res.getWidth()+"x"+res.getHeight())
    if (res.getWidth() > 1025){
        res.resize(1025, Jimp.AUTO)
        console.log("resized image size: "+res.getWidth()+"x"+res.getHeight())
     }
    res.getBase64(Jimp.AUTO, (err, value)=>{
        if(err){return err)}
        return value;
    })
}
const img =  await imgResize(base64data)

I get, SyntaxError: await is only valid in async functions and the top level bodies of modules.
But if I remove the async and just print the value without returning it, it works fine. So how I will able to get the value out of that function as return value and hold it in a variable?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You can’t return values inside an asynchronous callback and expect them to be assigned to a variable. Asynchronous callbacks are executed at a later point in time by Node.js at which point the execution context is lost. For example, this won’t work:

function getImageWidth(buffer) {
  Jimp.read(buffer, (err, res) => {
    // Outside context is lost and returning here doesn't
    // affect the return value of `getImageWidth` parent function
    return res.getWidth(); // won't work 🚫
  }
}

const width = getImageWidth(buffer);
console.log(width); // undefined

To accomplish what you want, you have two options:

  1. Use a promisified version of Jimp and keep using async/await
  2. Convert imgResize from async/await to use a callback

Turns out Jimp returns a promise if you don’t pass a callback function so going for solution #1 is most straightforward. Refactoring from callbacks to async/await would give us the following:

async function imgResize(data) {
  const buffer = Buffer.from(data, "base64");
  const res = await Jimp.read(buffer);
  console.log(`Original image size: ${res.getWidth()} x ${res.getHeight()}`);

  if (res.getWidth() > 1025){
    res.resize(1025, Jimp.AUTO);
    console.log(`Resized image size: ${res.getWidth()} x ${res.getHeight()}`);
  }
  
  return res.getBase64Async(Jimp.AUTO);
}

const img = await imgResize(base64data);

Note: For this to work you need to have top-level await enabled by using ES Modules (ESM). Otherwise you should wrap the last line in an IIFE:

(async () => {
  const img = await imgResize(base64data);
)();


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x