# catchError

<details>

<summary>Signatura</summary>

#### Firma

`catchError<T, O extends ObservableInput<any>>(selector: (err: any, caught: Observable<T>) => O): OperatorFunction<T, T | ObservedValueOf<O>>`

#### Parámetros

#### Retorna

`OperatorFunction<T, T | ObservedValueOf<O>>`: Un Observable que se puede originar en el Observable fuente o en el Observable retornado por la función `selector`.

</details>

## Descripción

`catchError` captura errores en el Observable fuente, manejándolos de dos maneras posibles: bien devolviendo un Observable nuevo o bien lanzando un nuevo error.

![Diagrama de canicas del operador catchError](https://github.com/puntotech/rxjs-docu/blob/master/doc/operators/error-handling/assets/images/marble-diagrams/error-handling/catchError.png)

## Ejemplos

**Capturar un error, retornando un Observable**

[StackBlitz](https://stackblitz.com/edit/docu-rxjs-catcherror?file=index.ts)

```javascript
import { throwError, of } from "rxjs";
import { catchError } from "rxjs/operators";

const error$ = throwError("¡Oh no!");

error$
  .pipe(catchError((error) => of(`Error capturado grácilmente: ${error}`)))
  .subscribe(console.log);
// Salida: Error capturado grácilmente: ¡Oh no!
```

**Capturar un error y lanzar otro error**

[StackBlitz](https://stackblitz.com/edit/docu-rxjs-catcherror-2?file=index.ts)

```javascript
import { throwError, of } from "rxjs";
import { catchError } from "rxjs/operators";

const error$ = throwError("Oh no!");

error$
  .pipe(
    catchError((error) => {
      throw `Lanzando un nuevo error: ${error}`;
    })
  )
  .subscribe(console.log, console.error);
// Salida: (Error) Lanzando un nuevo error: Oh no!
```

**Capturar los errores de un Observable interno**

Al capturar los errores que ocurren en un Observable interno (un Observable emitido por un Observable de orden superior), se debe tener cuidado a la hora de utilizar el operador `catchError` ya que, si se coloca en el sitio equivocado, el flujo del Observable fuente no seguirá ejecutándose tras capturar el error.

A continuación, se puede ver cómo el uso incorrecto de `catchError` hará que, después de capturar el error que devuelve la primera petición, el flujo se completará y no se harán las otras dos peticiones restantes:

[StackBlitz](https://stackblitz.com/edit/docu-rxjs-catcherror-inner?file=index.ts)

```javascript
import { map, concatMap, catchError } from "rxjs/operators";
import { ajax } from "rxjs/ajax";
import { of } from "rxjs";

const pokemonId$ = of(-3, 5, 6);

function getPokemonName(id: number) {
  return ajax
    .getJSON(`https://pokeapi.co/api/v2/pokemon/${id}`)
    .pipe(map(({ name }) => name));
}

pokemonId$
  .pipe(
    concatMap((id) => getPokemonName(id)),
    catchError((error) => of(`¡Oh no, ha ocurrido un error! ${error}`))
  )
  .subscribe(console.log, console.error, () => console.log("Completado"));
// Salida: ¡Oh no, ha ocurrido un error! AjaxError: ajax error 404, Completado
```

Sin embargo, si se utiliza `catchError` en el Observable interno, el comportamiento es el que se busca: cuando falle la primera petición, se capturará el error y el flujo seguirá ejecutándose, realizando las dos peticiones restantes:

[StackBlitz](https://stackblitz.com/edit/docu-rxjs-catcherror-inner-2?file=index.ts)

```javascript
import { map, concatMap, catchError } from "rxjs/operators";
import { ajax } from "rxjs/ajax";
import { of } from "rxjs";

const pokemonId$ = of(-3, 5, 6);

function getPokemonName(id: number) {
  return ajax
    .getJSON(`https://pokeapi.co/api/v2/pokemon/${id}`)
    .pipe(map(({ name }) => name));
}

pokemonId$
  .pipe(
    concatMap((id) =>
      getPokemonName(id).pipe(catchError((error) => of(`¡Oh no! ${error}`)))
    )
  )
  .subscribe(console.log, console.error, () => console.log("Completado"));
// Salida: ¡Oh no, ha ocurrido un error!, charmeleon, charizard, Completado
```

### Ejemplos de la documentación oficial

**Continuar con un Observable diferente cuando ocurre un error**

```javascript
import { of } from "rxjs";
import { map, catchError } from "rxjs/operators";

of(1, 2, 3, 4, 5)
  .pipe(
    map((n) => {
      if (n === 4) {
        throw "four!";
      }
      return n;
    }),
    catchError((err) => of("I", "II", "III", "IV", "V"))
  )
  .subscribe((x) => console.log(x));
// 1, 2, 3, I, II, III, IV, V
```

**Reiniciar el Observable fuente en caso de error, parecido al operador retry()**

```javascript
import { of } from "rxjs";
import { map, catchError, take } from "rxjs/operators";

of(1, 2, 3, 4, 5)
  .pipe(
    map((n) => {
      if (n === 4) {
        throw "four!";
      }
      return n;
    }),
    catchError((err, caught) => caught),
    take(30)
  )
  .subscribe((x) => console.log(x));
// 1, 2, 3, 1, 2, 3...
```

**Lanzar un error nuevo cuando el Observable fuente lance un error**

```javascript
import { of } from "rxjs";
import { map, catchError } from "rxjs/operators";

of(1, 2, 3, 4, 5)
  .pipe(
    map((n) => {
      if (n === 4) {
        throw "four!";
      }
      return n;
    }),
    catchError((err) => {
      throw "error en la fuente. Detalles: " + err;
    })
  )
  .subscribe(
    (x) => console.log(x),
    (err) => console.log(err)
  );
// 1, 2, 3, error en la fuente. Detalles: four!
```

### Recursos adicionales

[![Source code](https://github.com/puntotech/rxjs-docu/blob/master/doc/operators/error-handling/assets/icons/source-code.png)](https://github.com/ReactiveX/rxjs/blob/master/src/internal/operators/catchError.ts)

[Documentación oficial en inglés](https://rxjs.dev/api/operators/catchError)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.rxjs.es/operadores/error-handling/catcherror.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
