Обещание не разрешено, хотя ожидается

Я хотел бы получить пиксели из некоторых изображений и вернуть их в виде массива. Для обработки изображений я использую https://www.npmjs.com/package/jimp. В Jimp есть асинхронная функция jimp.read(filePath), которую нужно обрабатывать с помощью await. Мой модуль чтения изображений:

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;
}

Когда я запускаю код, я получаю массив с двумя элементами (потому что я предоставил два изображения). Оба Promise { <pending> }. Пожалуйста, взгляните на getInformationFromImageFile, функцию async, ожидающую jimp reader.

Почему он возвращает обещание и не разрешает его? Должен ли я ждать каждую функцию и весь модуль ...?

await jimp.read(filePath) работает и ожидает разрешения вызова. Однако вы не ожидаете вызова getInformationFromImageFile(imageFile) в getInformationFromImageFiles.
Olian04 10.02.2019 16:06

Что вы хотите, чтобы readImages вернул?

Mark 10.02.2019 16:18

массив файлов изображений

Question3r 10.02.2019 17:26

@ Olian04 извините, я все еще получаю обещание

Question3r 10.02.2019 17:26
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
4
485
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Вы также должны await функции getInformationFromImageFile().

извините, я все еще получаю обещание

Question3r 10.02.2019 17:25
Ответ принят как подходящий

Поскольку getInformationFromImageFile помечен как async, он вернет Promise, поэтому его нужно дождаться. Вам нужно await, где он называется. Эти изменения должны это исправить:

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);
}

Да, извините, мой плохой @MarkMeyer, отредактировал ответ и, надеюсь, теперь он правильный.

peter554 10.02.2019 16:50

извините, но я все еще получаю обещание

Question3r 10.02.2019 23:13

@Question3r При вызове readImages вам нужно будет подождать (или использовать синтаксис «тогда»), так как теперь это асинхронно, поэтому будет возвращено обещание. Вы ждете readImages?

peter554 10.02.2019 23:51

а, спасибо, теперь работает. Но, пожалуйста, обновите свою функцию getInformationFromImageFiles(imageFiles), imageFiles.push должен быть imageInfos.push, чтобы он работал :)

Question3r 11.02.2019 07:40

Как сказал другой участник, ваша функция должна быть awaited, поэтому она вернет обещание result.

Если вы хотите избежать функции awaiting, вы можете получить результат обещания синхронным способом, например так:

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

async/await так же, как обещания. Вы должны обрабатывать свои асинхронные возвраты так же, как вы обрабатываете промисы.

Всякий раз, когда вы вызываете асинхронную функцию, вы должны ждать ее в другой асинхронной функции или использовать .then(), как вы это делаете с промисами.

// 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);
}

Async/Await всегда возвращает обещание, поэтому вы можете сделать что-то вроде этого:

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

Другие вопросы по теме