Помимо takeUntil
мы также можем использовать оператор merge
или race
для обработки этого сценария. Однако это не меняет базовый логи c.
Шаг 1: Создайте Subject
для отдельной загрузки
file.cancelUpload$ = new Subject();
Шаг 2 : Объединить эту тему с фактическим вызовом http
слияние завершит поток, если какой-либо из наблюдаемых выдает ошибку. то есть, когда мы выдаем ошибку от субъекта cancelUpload$
, запрос http будет автоматически отменен (см. вкладку «Сеть»).
return merge(file.cancelUpload$, $http.pipe(...
Шаг 3: Фактический код отмены
cancelUpload(file: any) {
file.uploadStatus = "cancelled";
file.cancelUpload$.error(file.uploadStatus);// implicitly subject gets completed
}
Шаг 4. Заполните тему cancelUpload$
в случае ошибки / успеха загрузки
Это обеспечит выполнение операции merge
, поскольку оба потока сейчас завершено. И поэтому forkJoin
получит ответ.
См. https://stackblitz.com/edit/angular-zteeql?file=src%2Fapp%2Fhttp-example.ts
uploadFiles() {
let errorCount = 0,cancelledCount = 0, successCount = 0;
return forkJoin(
this.dummyFiles
.map(file =>
this.uploadFile(file).pipe(
catchError(() => of("Error re-emitted as success")) // value doesn't matter
)
)
).pipe(
map(() => { // map would receive array of files in the order it was subscribed
this.dummyFiles.forEach(file => {
switch (file.uploadStatus) {
case "success": successCount++; break;
case "cancelled": cancelledCount++; break;
case "error": errorCount++; break;
}
});
return { errorCount, successCount, cancelledCount };
})
);
}
uploadFile(file: any) {
const formData = new FormData();
const binaryContent = new Blob([Array(1000).join("some random text")], {
type: "text/plain"
}); // dummy data to upload
formData.append("file", binaryContent);
const $http = this.http.post(this.uploadUrl, formData, {
reportProgress: false
// observe: 'events',
// withCredentials: true
});
file.cancelUpload$ = new Subject();
file.uploadStatus = "inProgress";
return merge(
file.cancelUpload$,
$http.pipe(
tap(data => {
file.uploadStatus = "uploaded";
file.cancelUpload$.complete();
}),
catchError(event => {
file.uploadStatus = "error";
file.cancelUpload$.complete();
return throwError("error");
})
)
);
}