Я считаю полезным использовать службу для загрузки изображений, однако я не могу восстановить значение 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?





Вы рассматриваете это как синхронную операцию, но это не так. Вы должны использовать 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)
}
Спасибо. Я сделал несколько асинхронных обещаний на Node.js / Express. Приятно видеть, что я могу применить ту же логику и в Angular,
@ Джеймс надеется, что это помогло. Спасибо :)
еще кое-что ... как я могу установить типы ответа resolve({ File: file, Url: url }); на { File: File, Url: string }? Мой компонент ожидает здесь пустой json-объект const upload = await this.uploadService.uploadPhoto(event);
это resolve: (parameter) resolve: (value?: {} | PromiseLike<{}>) => void
@ Джеймс Извини, не знаю, о чем ты спрашиваешь.
Допустим, это решение обещания: resolve({ file, url });. когда он поступает на мой компонент, как получить значения file и url по отдельности?
@James ну тогда вы можете разрешить вот так resolve({file, url: reader.result})
да, но теперь это уже не пустой json {} ... это обманывает мой TSLint для всплывающих ошибок, потому что мой компонент ожидает {}
uploadPhoto(event: Event): Promise<{file: any, url: string}> { должно хватить
что, если я нахожусь внутри цикла файлов for (let i = 0; i < files.length; i++) { reader.onload = () => { resolve({file, url: reader.result}) }; }. Мне нужно разрешить после рендеринга всех файлов ... есть ли обходной путь?
тогда вы должны выполнить несколько обещаний и вернуть что-то вроде Promise.all
Это не работает ... после reject(), обещание продолжается, пока не достигнет reader.onload = () => { resolve() }
reject() означает только это, обещание завершится, как только вы сделаете resolve / reject
Понятно. Так что в моем компоненте будет примерно так:
const Promise = this.uploadService.uploadPhoto(event); Promise.then((upload) => { this.urlBanner = upload.Url; this.shop.banner = upload.File; }); }?