Quiero volver a intentar get la solicitud varias veces con un segundo retraso en caso de error, pero si todos los intentos fallaron, entonces ejecute el controlador de errores.
El siguiente código vuelve a intentar la solicitud, pero la captura nunca se ejecuta. ¿Cómo puedo arreglarlo?
import {Response, Http} from '@angular/http'; import {Observable} from 'rxjs/Rx'; import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/map'; this.http.get("/api/getData").map(data => { console.log('get') return data.json() }) .retryWhen(err => { console.log('retry') return err.delay(1000).take(5) }) .catch(err => { console.log('catch') this.handleHttpError(err) return err }) .subscribe(data => { console.log('subscribe') console.log(data) })El problema aquí es que cuando la notificación Observable devolvió la devolución de llamada en retryWhen envía la notificación complete , se propaga más como complete , que no es lo que desea de su descripción.
Desea enviarlo como notificación de error , lo que significa que no puede usar take() y usar algún otro operador para volver a generar el error.
Por ejemplo como este:
Observable.defer(() => Observable.throw("It's broken")) .retryWhen(err => { console.log('retry'); let retries = 0; return err .delay(1000) .map(error => { if (retries++ === 5) { throw error; } return error; }); }) .catch(err => { console.log('catch'); return Observable.of(err); }) .subscribe(data => { console.log('subscribe'); console.log(data); }); Puede contar el número de reintentos en la variable de retries usted mismo y, si alcanza algún límite, simplemente vuelva a generar el error. El operador map() envuelve todas las devoluciones de llamada con bloques try-catch, por lo que cualquier error arrojado en su invocable se enviará como señal de error .
Usando rxjs modernos con pipe , canalice el observable que está devolviendo en el operador retryWhen con alguna lógica que generará un error si se cumple una determinada condición.
https://stackblitz.com/edit/rxjs-retrywhen-to-catch
import { interval, of, throwError, timer } from 'rxjs'; import { catchError, mergeMap, switchMap, retryWhen, tap } from 'rxjs/operators'; const source = interval(1000); const example = source.pipe( // simulate error switchMap(count => count > 3 // this will be caught by retryWhen ? throwError('Error from source!') : of(count) ), retryWhen(err$ => err$.pipe( // display error from source tap(console.error), // i === index, AKA how many tries mergeMap((err, i) => i > 1 // throw error, which is caught by catchError // or second argument to subscribe function if catchError not used ? throwError('Error from retry!') // wait specified duration before retrying : timer(3000) ) )), catchError(err => of('There was an error, but we handled it. 😉')) ); example.subscribe( console.log, () => console.error('Nothing reaches this error handler because we used catchError') ); /* RESULT 0 1 2 3 Error from source! 0 1 2 3 Error from source! 0 1 2 3 Error from source! There was an error, but we handled it. 😉 */Inspirado en esta solución de learn-rxjs