Как правильно обрабатывать ошибки, используя retryWhen в rxjs - PullRequest
0 голосов
/ 03 апреля 2020

Мне нужно повторить заданный c вызов API примерно три раза при ошибке 502 неверного шлюза. Повторная попытка может произойти с незначительными задержками. Это код в компоненте.

some.component.ts

someMethod() {
    let attempt = 0;
    this.someService.AppendSubject(this.subject)
    .pipe(retryWhen(errors => errors.pipe(
        tap(error => this.retryApi(error, ++attempt, 'Server busy. Retrying request', this.subject))
    )))
    .subscribe(response => {
        //do something with response
    });
}

retryApi(error: any, attempt: number, retryMessage: string, data?: any) {
    delay(this.duration*attempt)
    //show toast with retryMessage
    if (attempt > this.retryLimit) {
        //show some message
        if (data)
            this.notifyFailure(data);
        throw error;
    }
}

notifyFailure(data: any) {
    this.someService.notifyFailure(data);
}

some.service.ts

public AppendSubject(data: any) {
    return this.http.post<any>(`{env.api}/appendsubject/`, data);
}    

public notifyFailure(data: any) {
    return this.http.post<any>(`{env.api}/notifyfailure/`, data);
}
  • Конечная точка notifyFailure вообще не используется на стороне сервера.

Это связано с тем, как я делаю / не выполняю перехват ошибок при повторных попытках? Как правильно перехватить ошибки в приведенном выше фрагменте кода и не препятствовать или не прекратить дальнейший вызов notifyFailure?

Примечание. В настоящее время я не делаю это в перехватчике, поскольку это только для определенных API c в эта точка. Я пишу обработчик повтора в компоненте, а не на уровне some.service.ts, так как я не знал, как это сделать, и пока показывал соответствующие тосты и всплывающие окна в компоненте.

Ответы [ 2 ]

1 голос
/ 03 апреля 2020

Добрый день! Я предпочитаю использовать такой подход:

Ваш сервис:

getSomething(retryCount: number = 0, retryInterval: number = 1000) {
    return this.http.get(this.getSomethingUrl).pipe(
      retryWhen((error: Observable<any>) => error.pipe(
        delay(retryInterval),
        take(retryCount)
      ))
    );
  }

В компоненте:

this.service.getSomething(3, 2000).subscribe(response => {
  // Handle success
}, error => {
  // Here you can send a request to your BE (triggers only after 3 failed requests in this case), to notify about the occurred error
  // Also you can do it in your pipe using `catchError` rxjs operator
});
0 голосов
/ 03 апреля 2020

Основываясь на ответе AlexanderFSP, я изменил свой код, чтобы таким образом отлавливать ошибки.

.pipe(retryWhen(errors => errors.pipe(
    tap(error => this.retryApi(error, ++attempt, 'Server busy. Retrying request', this.subject)),
    catchError(() => {
        this.notifyFailure(data);
        return EMPTY;
    })
)))
.subscribe(response => {
    //do something with response
});

Пока он работает.

...