Question3r
Question3r

Reputation: 3832

promise is not resolved although it gets awaited

I would like to get the pixels from some images and return them as an array. For the image handling I use https://www.npmjs.com/package/jimp . Jimp has an asynchronous function jimp.read(filePath) that needs to get handled with await. My image reader module:

const config = require('./configuration.json');
const fs = require('fs');
const path = require('path');
const jimp = require('jimp');

module.exports = readImages;

function readImages() { // Reads the image files and extracts the colors
    const files = getFilesFromDirectory();
    const imageFiles = filterForImageFiles(files);
    return getInformationFromImageFiles(imageFiles);
}

function getFilesFromDirectory() { // Reads all the files from the directory provided from the configuration file
    return fs.readdirSync(config.dirPath);
}

function filterForImageFiles(files) { // Filters an array of files for .png and .jpg files
    return files.filter(file => {
        const fileExtension = path.extname(file);
        const isPngFile = fileExtension === '.jpg';
        const isJpgFile = fileExtension === '.png';
        return isPngFile || isJpgFile;
    });
}

function getInformationFromImageFiles(imageFiles) { // Maps image files to image information
    return imageFiles.map(imageFile => getInformationFromImageFile(imageFile));
}

async function getInformationFromImageFile(imageFile) { // Extracts information from an image file
    const filePath = path.join(config.dirPath, imageFile);
    const image = await jimp.read(filePath);
    return getColorsFromImage(image);
}

function getColorsFromImage(image) { // Extracts the colors from an image file
    const { width, height } = image.bitmap;
    const colors = [,];
    for (let x = 0; x < width; x++) {
        for (let y = 0; y < height; y++) {
            const intColor = image.getPixelColor(x, y);
            const rgbaColor = jimp.intToRGBA(intColor);
            colors[x, y] = rgbaColor;
        }
    }
    return colors;
}

When I run the code I receive an array with two items (because I provided two images). Both are Promise { <pending> }. Please have a look at getInformationFromImageFile which is an async function awaiting the jimp reader.

Why does it return a promise and does not resolve it? Do I have to await every function and the whole module ... ?

Upvotes: 3

Views: 693

Answers (5)

Harry
Harry

Reputation: 1432

Async/Await always returns Promise, so you can do something like this:

Promise
  .all(readImages())
  .then(imd => console.log(imd))
  .catch(error => console.log(error));`

Upvotes: 0

peter554
peter554

Reputation: 1378

As getInformationFromImageFile is marked async it will return a Promise therefore it must be awaited. You need to await where it is called. These changes should fix it:

async function getInformationFromImageFiles(imageFiles) {
    const imageInfos = [];
    for (let i = 0; i < imageFiles.length; i++) {
        const imageFile = imageFiles[i];
        imageInfos.push(await getInformationFromImageFile(imageFile));
    }

    return imageInfos;
}

async function readImages() {
    const files = getFilesFromDirectory();
    const imageFiles = filterForImageFiles(files);
    return await getInformationFromImageFiles(imageFiles);
}

Upvotes: 4

Dinesh Pandiyan
Dinesh Pandiyan

Reputation: 6299

async/await is just like promises. You gotta handle your async returns like you handle promises.

Whenever you invoke an async function, you gotta await it in another async function or use .then() like you do with promises.

// make this function async
async function readImages() {
  // Reads the image files and extracts the colors
  const files = getFilesFromDirectory();
  const imageFiles = filterForImageFiles(files);
  // the next line is an async call - so await it
  const images = await getInformationFromImageFiles(imageFiles); // array of images
  return images;
}

function getFilesFromDirectory() {
  // Reads all the files from the directory provided from the configuration file
  return fs.readdirSync(config.dirPath);
}

function filterForImageFiles(files) {
  // Filters an array of files for .png and .jpg files
  return files.filter((file) => {
    const fileExtension = path.extname(file);
    const isPngFile = fileExtension === '.jpg';
    const isJpgFile = fileExtension === '.png';
    return isPngFile || isJpgFile;
  });
}

// make this function async
async function getInformationFromImageFiles(imageFiles) {
  // promisify all async returns
  return Promise.all(imageFiles.map((imageFile) => getInformationFromImageFile(imageFile)));
}

// return async
async function getInformationFromImageFile(imageFile) {
  // Extracts information from an image file
  const filePath = path.join(config.dirPath, imageFile);
  const image = await jimp.read(filePath);
  return getColorsFromImage(image);
}

Upvotes: 0

garry man
garry man

Reputation: 465

As other member said, your function needs to be awaited hence it will return the promise result.

If you want to avoid awaiting the function, you can get your promise result in a synchronous way, like this:

let x = new Promise(function(){
//code
});
x.then(function(data){
   //Promise resolved, do something
}).then(function(err){
   //Promise rejected, do something
});

Upvotes: -1

user835611
user835611

Reputation: 2376

You also need to await the function getInformationFromImageFile().

Upvotes: 0

Related Questions