@Dyadko_Orest

Как вернуть значение из асинхронной функции?

Есть функция, которая принимает url картинки и которая должна возвращать высоту и ширину этой картинки. Размеры считает хорошо, но у меня возникли проблемы с тем, чтобы возвратить значения width и height. У меня получилось реализовать только через promise, но этот вариант мне не подходит. Как написать эту функцию (можно с async await), чтобы она возвращала width и height?

const getImageSize = async (imageDataUrl: string) => {
    const image = new Image();
    image.src = imageDataUrl;

    let width = null;
    let height = null;

    image.onload = () => {
      width = image.width;
      height = image.height;
      return { width, height };
    }; 
  ///я пробивал так

   return  image.onload = () => {
      const width = image.width;
      const height = image.height;
      return { width, height };
    }; // не работает

  let width = null;
  let height = null
  image.onload = () => {
      width = image.width;
      height = image.height;
    }; 

     return { width, height };// не работает
  };

const {widht, height} = getImageSize(imageDataUrl)
  • Вопрос задан
  • 1184 просмотра
Пригласить эксперта
Ответы на вопрос 3
@DimaIs
Async/await вам в этом случае не поможет, необходимо переделать реализацию под промисы
Статься про промисы
Касательно решения: вам необходимо резолвить промис со значением в виде обьекта с необходимыми данными, промис резолвится функцией resolve, которая передается первым аргументом коллбека, передаваемого в конструктор промиса:
interface IImageSize {
    width: number;
    height: number;
}

const getImageSize = (imageDataUrl: string): Promise<IImageSize> =>
    new Promise((resolve): void => {
        //Создаем промис, его же и возвращаем
        const image = new Image();
        image.src = imageDataUrl;

        image.onload = () => {
            const { width, height } = image;
            const imageSize: IImageSize = {
                width,
                height,
            };
            resolve(imageSize); // резолвим промис с необходимым нам обьектом
        };
    });

 // вызываем функцию либо внутри другой асинхронной функции, дабы был доступен оператор await
const anyFunction = async (): Promise<void> => {
    const imageSize: IImageSize = await getImageSize("<any_image_url>");
    const { width, height } = imageSize;
};

//либо поступаем как с любым другим промисом
getImageSize("<any_image_url>").then((imageSize: IImageSize): void => {
    const { width, height } = imageSize;
});
Ответ написан
Krasnodar_etc
@Krasnodar_etc
fundraiseup
Во-первых, в getImageSize async(асинхронная)-функция , они всегда возвращают промис. Чтобы получить её результат, вам нужно написать либо await getImageSize(imageDataUrl), либо getImageSize(imageDataUrl).then(result => { console.log(result); });

А дальше давайте разбирать все три примера:
1 - getImageSize ничего не возвращает, она добавляет к картинке слушатель onload , который возвращает (в никуда) width, height

2 - getImageSize возвращает результат присваивания функции в image.onload , в данном случае, саму функцию, которую вы присваиваете

3 - наиболее похожий на правду вариант, но с одной ошибкой - ваш код синхронный, возврат значения отрабатывает раньше, чем произойдёт событие load и в переменных появятся правильные значения

Рабочий алгоритм getImageSize должен быть такой:
1 - Создаётся объект Image + указывается src (это у вас правильно)
2 - Вешается слушатель onload на изображение
3 - Когда этот слушатель выполняется, можно прочитать размеры из Image и вернуть их

С моей точки зрения без Промисов это нельзя написать, если только не пересматривать вообще весь ваш код
Ответ написан
Комментировать
Stalker_RED
@Stalker_RED
const getImageSize = async (imageDataUrl) => {
  return new Promise((resolve, reject) => {
    let img = new Image();
    img.onload = () => resolve({w:img.width, h:img.height});
    img.onerror = reject;
    img.src = imageDataUrl;
  });
};


getImageSize('https://via.placeholder.com/200x100').then(console.log); // так подхродит?

Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы