Angular - как создать службу загрузки файлов?

Я считаю полезным использовать службу для загрузки изображений, однако я не могу восстановить значение url, установленное после render.onload.

// service
export class UploadService {

  constructor(private alertService: AlertService) {}

  uploadPhoto(event: Event) {
      const file = (event.target as HTMLInputElement).files[0];

      if (file.type === 'image/png' || file.type === 'image/jpeg' || file.type === 'image/jpg') {
          const reader = new FileReader();
          let url;
          reader.onload = () => {
              url = reader.result;
          };
          reader.onerror = (error: any) => {
              this.alertService.error(`Error ao carregar a imagem: ${error}`);
              return;
          };
          reader.readAsDataURL(file);
          return { File: file, Url: url };
      } else {
          this.alertService.error('Formato inválido. Somente imagens do formato Png, Jpeg e Jpg são permitidos.');
          return;
      }
  }
}

// component
uploadBanner(event: Event) {
  const Upload = this.uploadService.uploadPhoto(event);
  if (Upload) {
    this.urlBanner = Upload.Url;
    this.shop.banner = Upload.File;
  }
}

Как я могу восстановить url и file?

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
0
491
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы рассматриваете это как синхронную операцию, но это не так. Вы должны использовать Promise или Observable для решения этой проблемы. И верните данные при запуске события onload.

export class UploadService {

  constructor(private alertService: AlertService) {}

  uploadPhoto(event: Event): Promise<{file: any, url: string}> { {
    return new Promise((resolve, reject) => {
      const file = (event.target as HTMLInputElement).files[0];

      if (file.type === 'image/png' || file.type === 'image/jpeg' || file.type === 'image/jpg') {
        const reader = new FileReader();
        let url;
        reader.onload = () => {
          resolve({file, url: reader.result})
        };
        reader.onerror = (error: any) => {
          this.alertService.error(`Error ao carregar a imagem: ${error}`);
          reject(error)
        };
        reader.readAsDataURL(file);
      } else {
        let error = 'Formato inválido. Somente imagens do formato Png, Jpeg e Jpg são permitidos.'
        this.alertService.error(error);
        reject(error);
      }
    }
  }
}

Составная часть

// component
uploadBanner = async (event: Event) => {
  const url = await this.uploadService.uploadPhoto(event);
  console.info(url)
}

Понятно. Так что в моем компоненте будет примерно так: const Promise = this.uploadService.uploadPhoto(event); Promise.then((upload) => { this.urlBanner = upload.Url; this.shop.banner = upload.File; }); }?

James 18.10.2018 20:30

Спасибо. Я сделал несколько асинхронных обещаний на Node.js / Express. Приятно видеть, что я могу применить ту же логику и в Angular,

James 18.10.2018 20:41

@ Джеймс надеется, что это помогло. Спасибо :)

Pankaj Parkar 18.10.2018 20:41

еще кое-что ... как я могу установить типы ответа resolve({ File: file, Url: url }); на { File: File, Url: string }? Мой компонент ожидает здесь пустой json-объект const upload = await this.uploadService.uploadPhoto(event);

James 18.10.2018 21:26

это resolve: (parameter) resolve: (value?: {} | PromiseLike<{}>) => void

James 18.10.2018 21:30

@ Джеймс Извини, не знаю, о чем ты спрашиваешь.

Pankaj Parkar 18.10.2018 21:32

Допустим, это решение обещания: resolve({ file, url });. когда он поступает на мой компонент, как получить значения file и url по отдельности?

James 18.10.2018 21:35

@James ну тогда вы можете разрешить вот так resolve({file, url: reader.result})

Pankaj Parkar 18.10.2018 21:39

да, но теперь это уже не пустой json {} ... это обманывает мой TSLint для всплывающих ошибок, потому что мой компонент ожидает {}

James 18.10.2018 21:42
uploadPhoto(event: Event): Promise<{file: any, url: string}> { должно хватить
Pankaj Parkar 18.10.2018 21:55

что, если я нахожусь внутри цикла файлов for (let i = 0; i < files.length; i++) { reader.onload = () => { resolve({file, url: reader.result}) }; }. Мне нужно разрешить после рендеринга всех файлов ... есть ли обходной путь?

James 18.10.2018 22:48

тогда вы должны выполнить несколько обещаний и вернуть что-то вроде Promise.all

Pankaj Parkar 18.10.2018 22:50

Это не работает ... после reject(), обещание продолжается, пока не достигнет reader.onload = () => { resolve() }

James 23.10.2018 07:01
reject() означает только это, обещание завершится, как только вы сделаете resolve / reject
Pankaj Parkar 23.10.2018 08:10

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