The problem is that queries in the forkjoin array continue to execute even if the previous one failed. For example, already in the first request putCategory$ an error occurred (the name already exists). However, the next loadImage$ request is executed and the new image is still loaded. Why? How to make a sequence of requests so that if a failure occurs, the next ones will not be executed?
PUTCategory(category: ICategory) {
const newImage = category.image;
const oldImage = this.editedCategory.image;
const imageChanged = oldImage !== newImage;
const loadImage = imageChanged && !!newImage;
const deleteImage = imageChanged && !!oldImage;
const file: File = this.form.value.image;
const putCategory$ = this.categoryService.putCategory(category).pipe(
catchError((response: any) => {
if (response.error.info == 'NAME_EXISTS') {
this.throwErrorModal(
'Категория с таким названием уже существует. Измените название и попробуйте снова.',
);
} else {
this.throwErrorModal(
'Произошла ошибка при попытке обновить категорию',
);
}
return EMPTY;
}),
);
const loadImage$ = loadImage
? this.categoryService.uploadCategoryImage(file).pipe(
catchError(() => {
this.throwErrorModal(
'Произошла ошибка при попытке загрузить файл нового изображения категории',
);
return EMPTY;
}),
concatMap((response: any) => {
const filename = response.filename;
return this.categoryService
.setImageToCategory(category.id, filename)
.pipe(
catchError(() => {
this.throwErrorModal(
'Произошла ошибка при попытке связать новое загруженное изображение и категорию',
);
return EMPTY;
}),
);
}),
)
: of(null);
const deleteImage$ = deleteImage
? this.categoryService.deleteImage(oldImage!).pipe(
catchError(() => {
this.throwErrorModal(
'Произошла ошибка при попытке удалить старое изображение категории',
);
return EMPTY;
}),
concatMap(() => {
return this.categoryService
.setImageToCategory(category.id, '')
.pipe(
catchError(() => {
this.throwErrorModal(
'Произошла ошибка при попытке удаления связи старого изображения с категорией',
);
return EMPTY;
}),
);
}),
)
: of(null);
forkJoin([putCategory$, deleteImage$, loadImage$])
.pipe(
finalize(() => {
this.awaitModal = false;
this.cdr.markForCheck();
}),
tap(() => {
this.successModal = true;
}),
)
.subscribe();
}
Just in case, throwErrorModal is my simple function
private throwErrorModal(content: string) {
this.errorModalContent = content;
this.errorModal = true;
}