У меня есть код, который выполняет загрузку большого файла небольшими порциями. Вот что у меня есть:
upload(project: Project): Observable<any> {
var chunks = this.chunkFiles(project);
var totalPercent = project.file
.map(file => Math.ceil(file.size / this.chunkSize))
.reduce((sum, curr) => sum + curr) * 100;
var finishedPercent = 0;
var currentPercent = 0;
return from(chunks)
.pipe(
concatMap(request =>
{
return this.http.request(request)
.pipe(
retryWhen(error =>
{
return interval(1000)
.pipe(
flatMap(count =>
{
if (count == 2)
{
return throwError(error);
}
return of(count);
})
);
}));
}),
map(event =>
{
if (event.type === HttpEventType.UploadProgress)
{
var progress = event as HttpProgressEvent;
currentPercent = Math.round(100 * progress.loaded / progress.total);
return {
type: event.type,
loaded: finishedPercent + currentPercent,
total: totalPercent
};
}
else if (event instanceof HttpResponse)
{
finishedPercent += 100;
if (finishedPercent == totalPercent)
{
return event;
}
}
}),
filter(response => response !== undefined)
);
}
Предполагается, что он начинает загрузку фрагментов файла, и после сбоя одной из загрузок фрагмента он должен остановиться, и ошибка должна распространиться до кода, вызывающего мою функцию загрузки. Этот конкретный код выглядит следующим образом:
onStartUpload = this.actions$
.ofType(forRoot.START_UPLOAD).pipe(
switchMap((action: forRoot.StartUpload) =>
this.uploadService
.upload(action.project).pipe(
map((event) => {
if (event.type === HttpEventType.UploadProgress) {
const progress = event as HttpProgressEvent;
const percentDone = Math.round(100 * progress.loaded / progress.total);
return new forRoot.UploadProgress(percentDone);
} else if (event instanceof HttpResponse) {
return new forRoot.UploadSucceeded();
} else {
console.log(event);
}
}),
filter(a => a !== undefined),
catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 400) {
const message = this.getMessage(error);
return of(new forRoot.UploadFailed(message || "Bad request"));
} else {
return of(new forRoot.UploadFailed("Network error"));
}
})))
);
Проблема в том, что я получаю только сообщение «Ошибка сети», в то время как я ожидаю что-то со статусом ошибки 400 (поэтому я должен получать либо конкретное сообщение, либо «Плохой запрос».
Я предполагаю, что неправильно обрабатываю ошибку в retryWhen, но я пробовал несколько разных идей, и ни одна из них, похоже, не работает. Чего мне не хватает?
Изменить, чтобы показать рабочий код без повторных попыток:
Вот код с корректной обработкой сообщений об ошибках, но без повторных попыток:
return from(chunks)
.pipe(
concatMap(request =>
{
return this.http.request(request)
}),
map(event =>
{
if (event.type === HttpEventType.UploadProgress)
{
var progress = event as HttpProgressEvent;
currentPercent = Math.round(100 * progress.loaded / progress.total);
return {
type: event.type,
loaded: finishedPercent + currentPercent,
total: totalPercent
};
}
else if (event instanceof HttpResponse)
{
finishedPercent += 100;
if (finishedPercent == totalPercent)
{
return event;
}
}
}),
filter(response => response !== undefined)
);
Я предполагал, что есть что-то, что я могу добавить к вызову http.request, чтобы повторить указанное количество раз с задержкой между попытками, а затем, если все они завершатся неудачно, вывести ошибку, как это делает http.request. , Кажется, что происходит то, что он проходит после кода concatMap к коду карты. Я могу добавить вызов console.log (событие) и посмотреть сообщение об ошибке, возвращаемое с сервера. Я все еще довольно новичок в rxjs, так что, может быть, я не понимаю, но я ожидал, что как только ошибка произойдет, она не выполнит код карты.