Gestione degli errori RxJS utilizzando catchError()
Tempo di lettura: 4 minuti

La gestione degli errori svolge un ruolo essenziale in quasi tutte le applicazioni, doppiamente quando si tratta di chiamate di rete. Per questo motivo, librerie come RxJS includono un’ampia varietà di meccanismi per gestire gli errori di ogni tipo concepibile in modo grazioso. In effetti, RxJS si presta a così tante strategie di gestione degli errori che gli sviluppatori spesso non sono sicuri di quale utilizzare per una determinata situazione. Questo tutorial di sviluppo web mira a chiarire la confusione fornendo alcuni esempi concreti che puoi seguire nella tua codifica.

Successo, errore, completamento ≠ Prova, cattura, finalmente

All’osservazione iniziale, i tre RxJS sottoscrivi() i parametri della funzione hanno una stretta somiglianza con il Tentativo, presa, finalmente blocchi della tradizionale gestione degli errori JavaScript (JS). In effetti, sono simili in diversi modi:

  • In entrambi i casi, il completare() la funzione e infine il blocco sono opzionali.
  • Il errore() function e catch block ci consentono entrambi di gestire gli errori in modo aggraziato.
  • Sia il errore() function e catch block ci danno la possibilità di gestire noi stessi l’errore.

Al di là di queste somiglianze, le funzioni di successo, errore e complete di RxJS differiscono dalla sua controparte sincrona JS per un aspetto molto importante:

Mentre il blocco finally viene eseguito indipendentemente da ciò che accade prima, il completare() La funzione viene invocata solo se il flusso viene completato, ovvero se il flusso non genera errori.

Leggere: Graziosa gestione degli errori RxJS

Possiamo verificare tale comportamento abbastanza facilmente recuperando un URL valido e non valido utilizzando HttpClient’s ottenere metodo:

import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ],
  providers: [HttpClient]
})
export class AppComponent  {

  constructor(private http: HttpClient) {}

  ngOnInit() {
    const http$ = 
      this.http.get(
        'mattree-node-highlighting-demo?file=main.ts', 
        {responseType: 'text'}
      ); 

    http$.subscribe({
      next: (res) => console.log(res),
      error: (err) => console.error(err),
      complete: () => console.info('complete') 
    });
  }
}

Possiamo vedere che sia il contenuto HTML che il messaggio “completo” sono stati stampati sulla console:

La modifica del parametro URL in qualcosa che non riesce ora genera solo l’errore:

Gestione degli errori in RxJS

Ora immagina di voler mostrare una finestra di dialogo dopo a INVIARE operazione che aggiorna i permessi dell’utente. Potresti voler trasmettere un messaggio di errore come segue:

constructor(public dialogRef: MatDialog) { }

const dialogConfig = new MatDialogConfig();
this.appService.updatePermissions(this.permissionId, this.permissions)
  .subscribe(
    () => '',
    (err) => dialogConfig.data = { err: err ? err : "Something went wrong! Couldn't save permissions." },
    () => this.dialogRef.open(DialogComponent, dialogConfig)
  );

Sapendo cosa facciamo ora su come funzionano i gestori delle iscrizioni, è ovvio che la finestra di dialogo non apparirà quando si verifica un errore.

Leggere: RxJS Observables Primer in angolare

Continuando in caso di errore nella gestione degli errori RxJS

Per far funzionare il codice sopra come previsto, dobbiamo catturare l’errore prima del sottoscrivi e invia lo stato di errore per la gestione lì. A tale scopo, esiste il carchError() operatore. Può restituire un nuovo osservabile (o errore) in modo da poter registrare l’errore a scopo di debug e quindi restituire un booleano che indica che si è verificato un errore.

Il sottoscrivi() ora riceverà l’errore osservabile in modo che possa far sapere alla finestra di dialogo se l’operazione di salvataggio è andata a buon fine:

interface SaveDialogData {
  success?: boolean;
}

this.appService.updatePermissions(this.permissionId, this.permissions)
  .pipe(
    catchError(err => {
      if (err) {
        console.error(err);
      }
      return of(err != null);
    })
  )
  .subscribe((err: boolean) => {
    const dialogConfig = new MatDialogConfig<SaveDialogData>();
    if (err) {
      dialogConfig.data = { success: false };
    }
    this.dialogRef.open(NewsDialogComponent, dialogConfig);
  });

Questo particolare tipo di trattamento degli errori è noto come “Strategia Catch and Replace”, per cui catchError() viene utilizzato per fornire un Osservabile sostitutivo che emetta uno o più valori di fallback. Il trucco per far funzionare questa strategia è passare qualsiasi valore di sostituzione che vogliamo inviare al di() metodo. Può accettare una quantità variabile di valori in una sequenza e quindi emette immediatamente una notifica completa. È simile a da()ma non esegue alcun appiattimento ed emette ogni argomento per intero come una notifica successiva.

Ecco la sua firma:

of<T>(...args): Observable<T>

Quindi, anche se stiamo inviando un solo valore booleano, avremmo potuto facilmente passare un array di valori come segue:

return of(err, this.permissionId, this.permissions);

Leggere: Esecuzione di RxJS 6 osservabili in ordine

Accedere al successo Booleano nel componente Dialogo

Nel Componente di dialogo classe, possiamo iniettare il dati tramite il costruttore e imposta la variabile public di conseguenza:

export class DialogComponent implements OnInit {
  public success: boolean = true;

  constructor(
    @Inject(MAT_DIALOG_DATA) public data: SaveDialogData
  ) { }

  ngOnInit(): void {
    if (this.data?.success === false) {
      this.success = false;
    }
  }
}

Questa tecnica fornisce un ulteriore vantaggio che il messaggio di dialogo può essere impostato nel modello, rendendo molto più semplice la traduzione se necessario:

<h2 mat-dialog-title>Save Permissions</h2>
<div mat-dialog-content>
  {{success ? "Permissions have been successfully saved" : "Something went wrong! Couldn't save permissions."}}
</div>
<div mat-dialog-actions>
    <button mat-button mat-dialog-close>Close</button>
</div> 

La demo catchError() RxJS

Per capire meglio il catchError() operatore, ecco a demo completamente modificabile che mostra cosa succede quando una chiamata API viene restituita correttamente e gli errori vengono eliminati. Ciò si ottiene tramite due pulsanti.

Il Invia richiesta valida emula un’operazione di salvataggio riuscita:

Gestione degli errori RxJS

Il Invia richiesta non valida emula un’operazione di salvataggio non riuscita:

RxJS Come gestire gli errori

Conclusione sulla gestione degli errori RxJS utilizzando catchError()

Sebbene sia simile al blocco finale della tradizionale gestione degli errori JavaScript (JS), RxJS sottoscrivi() metodo completare() Il parametro function non viene richiamato quando una chiamata asincrona termina in errore. Per tale motivo, il catchError() operatore è la soluzione migliore per gestire gli errori quando si desidera continuare a verificare se si verifica o meno un errore.

Per saperne di più RxJS e tutorial di sviluppo web.

Source link

Di Simone Serra

Web Designer Freelancer Realizzazione Siti Web Serra Simone Realizzo siti web, portali ed e-commerce con focus specifici sull’usabilità, l’impatto grafico, una facile gestione e soprattutto in grado di produrre conversioni visitatore-cliente. Elaboro siti internet, seguendo gli standard Web garantendo la massima compatibilità con tutti i devices. Sviluppo e-commerce personalizzati, multilingua, geolocalizzati per potervi mettere nelle migliori condizioni di vendita. Posiziono il tuo sito su Google per dare maggiore visibilità alla tua attività sui motori di ricerca con SEO di base o avanzato.