Angular - 异步方法不返回被拒绝的承诺



我在组件中使用async方法上传文件。喜欢这个:

//component
uploadPhotos = async (event: Event) => {
const upload = await this.uploadService.uploadPhotos(event, this.files, this.urls);
}

UploadService在调用上载后返回包含更新的文件和路径文件的promise。该服务正在按预期工作,promise达到resolve()而没有任何挫折。但是,如果调用reject(),代码将继续运行,直到到达reader.onload()内部的resolve()

// service
uploadPhotos(event: Event, oldFiles: File[], oldUrls: string[]): Promise<{files: File[], urls: string[]}> {
return new Promise((resolve, reject) => {
const files = (event.target as HTMLInputElement).files;
if ((files.length + oldFiles.length) > 5) {
this.alertService.error('Número máximo de fotos permitidos é 5.');
reject();
// there is an error, so it reaches here first
}

for (let i = 0; i < files.length; i++) {
const exists = oldFiles.findIndex(file => file.name === files[i].name);
if (exists === -1) {
if (files[i].type === 'image/png' || files[i].type === 'image/jpeg') {
oldFiles.push(files[i]);
const reader = new FileReader();
reader.onerror = (error: any) => {
this.alertService.error(`Erro ao carregar a imagem: ${error}`);
reject();
};
reader.readAsDataURL(files[i]);
reader.onload = () => {
// it reaches here after reject()
oldUrls.push(reader.result);
if (i === files.length - 1) { resolve({ files: oldFiles, urls: oldUrls }); }
};
} else {
this.alertService.error('Formato inválido. Somente imagens do formato Png, Jpeg e Jpg são permitidos.');
reject();
}
}
}
});
}

如果在resolve()之前达到reject(),有没有办法避免该reader.onload()块?

是的,reject()resolve()是普通(回调(函数调用。它们与控制流无关,它们不会停止您的函数。为此使用returnif/else

此外,您的new Promise内有一个循环。如果一个文件读取器中发生错误,则对其他文件读取器没有影响。我建议在最内在的层面上进行承诺。然后写

readFile(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onerror = (error: any) => reject(error);
reader.onload = () => resolve(reader.result);
reader.readAsDataURL(file);
});
}
// service
async uploadPhotos(event: Event, oldFiles: File[], oldUrls: string[]): Promise<{files: File[], urls: string[]}> {
try {
const files = (event.target as HTMLInputElement).files;
if ((files.length + oldFiles.length) > 5) {
throw new Error('Número máximo de fotos permitidos é 5.');
}
const newFiles = Array.from(files).filter(newFile =>
!oldFiles.some(oldFile => oldFile.name === newFile.name)
);
if (!newFiles.every(file => file.type === 'image/png' || file.type === 'image/jpeg' || file.type === 'image/jpg')) {
throw new Error('Formato inválido. Somente imagens do formato Png, Jpeg e Jpg são permitidos.');
}
const newUrls = await Promise.all(newFiles.map(file =>
this.readFile(file).catch(error => {
throw new Error(`Erro ao carregar a imagem: ${error}`);
})
));
return {
files: oldFiles.concat(newFiles),
urls: oldUrls.concat(newUrls)
};
} catch(err) {
this.alertService.error(err.message);
throw new Error("something went wrong during file upload");
}
}

您可以添加load侦听器,然后在error处理程序中删除它,以确保load侦听器不会触发:

reader.onerror = (error: any) => {
this.alertService.error(`Erro ao carregar a imagem: ${error}`);
reader.removeEventListener('load', loadHandler);
reject();
};
reader.readAsDataURL(files[i]);
const loadHandler = () => {
oldUrls.push(reader.result);
if (i === files.length - 1) {
resolve({ files: oldFiles, urls: oldUrls });
}
};
reader.addEventListener('load', loadHandler);

最新更新