node.jses6-promisejimp

Why is my try-catch exception with nested async function not throwing?


I want to get some images, so I wrote a promise based script to get images from a chosen image url. However, when an invalid url is supplied it is supposed to return "Get Error." But instead (as I can see), the application crashes, and thus the try-catch block is not working.

const Jimp = require("jimp");

function rgba(source, width, height) {
  return new Promise((resolve, reject) => {
    try {
      resolve((async () => {
        const image = await Jimp.read(source);
        const resized = image.resize(width, height);
        const rgbaArray = [];

        for (y = 0; y < height; y++) {
          for (x = 0; x < width; x++) {
            rgbaArray.push(Jimp.intToRGBA(resized.getPixelColor(x, y)));
          };
        };

        return rgbaArray;
      })());
    } catch {
      reject("Get Error");
    };
  });
};

// Returns correct result.
rgba(
  "https://upload.wikimedia.org/wikipedia/commons/9/9e/SpaceX_Crew-1_Launch_%28NHQ202011150029%29.jpg", 
  50, 
  50
).then(resolve => {
  console.log(resolve);
}).catch(reject => {
  console.log(reject);
}); 

// App crashes instead of logging "Get Error."
rgba(
  "improper_url", 
  50, 
  50
).then(resolve => {
  console.log(resolve);
}).catch(reject => {
  console.log(reject);
}); 


Solution

  • Use try...catch to handle the async/await calls directly.

    function rgba(source, width, height) {
      return new Promise(async (resolve, reject) => {
        try {
          const image = await Jimp.read(source);
          const resized = image.resize(width, height);
          const rgbaArray = [];
          for (y = 0; y < height; y++) {
            for (x = 0; x < width; x++) {
              rgbaArray.push(Jimp.intToRGBA(resized.getPixelColor(x, y)));
            }
          }
          resolve(rgbaArray);
        } catch {
          reject('Get Error');
        }
      });
    }
    

    Or, do your job and let the caller method handle the possible exception:

    async function rgba(source, width, height) {
      const image = await Jimp.read(source);
      const resized = image.resize(width, height);
      const rgbaArray = [];
      for (y = 0; y < height; y++) {
        for (x = 0; x < width; x++) {
          rgbaArray.push(Jimp.intToRGBA(resized.getPixelColor(x, y)));
        }
      }
      return rgbaArray;
    }
    

    in the caller method you can handle error easily:

    async function handler() {
      try {
        const result = await rgba(/* args */);
      } catch (e) {
        console.error(e);
      }
    }
    

    Handle by Promise:

    function handlerPromise() {
      rgba(/* args */)
          .then(result => {
            console.log(result);
          })
          .catch(err => {
            console.error(err);
          });
    }