131 votes

Comment générer une erreur de l'opérateur de carte RxJS (angulaire)

Je souhaite émettre une erreur de l'opérateur cartographique de mon observable en fonction d'une condition. Par exemple, si les données d'API correctes ne sont pas reçues. S'il vous plaît voir le code suivant:

 private userAuthenticate( email: string, password: string ) {
    return this.httpPost(`${this.baseApiUrl}/auth?format=json&provider=login`, {userName: email, password: password})
        .map( res => { 
            if ( res.bearerToken ) {
                return this.saveJwt(res.bearerToken); 
            } else {
                // THIS DOESN'T THROW ERROR --------------------
                return Observable.throw('Valid token not returned');
            }
        })
        .catch( err => Observable.throw(this.logError(err) )
        .finally( () => console.log("Authentication done.") );
}
 

Fondamentalement, comme vous pouvez le constater dans le code, si la réponse (objet res) n'a pas 'bearerToken', je souhaite supprimer une erreur. Ainsi, dans mon abonnement, il entre dans le deuxième paramètre (handleError) mentionné ci-dessous.

 .subscribe(success, handleError)
 

Aucune suggestion?

186voto

Martin Points 1093

Il suffit de jeter l'erreur à l'intérieur de l' map() de l'opérateur. Tous les rappels dans RxJS sont enveloppées avec des blocs try-catch donc il sera capturé et envoyé en tant que error de notification.

Cela signifie que vous ne retourne rien, et il suffit de jeter l'erreur:

map(res => { 
  if (res.bearerToken) {
    return this.saveJwt(res.bearerToken); 
  } else {
    throw new Error('Valid token not returned');
  }
})

L' throwError() (ex - Observable.throw() dans RxJS 5) est une Observable qui envoie juste un error de notification, mais map() ne se soucie pas ce que vous en retour. Même si vous retournez un Observables de l' map() il va être passé en next de notification.

Dernière chose, vous n'avez probablement pas besoin d'utiliser .catchError() (ex - catch() dans RxJS 5). Si vous avez besoin d'effectuer des effets secondaires lorsqu'une erreur se produit, il est préférable d'utiliser tap(null, err => console.log(err)) (ex - do() dans RxJS 5) par exemple.

Jan 2019: mise à Jour pour RxJS 6

47voto

Simon_Weaver Points 31141

Si vous vous sentez comme throw new Error() semble onu-observable-comme vous pouvez l'utiliser switchMap:

// RxJS 6+ syntax
this.httpPost.pipe(switchMap(res => { 
   if (res.bearerToken) {
      return of(this.saveJwt(res.bearerToken)); 
   } 
   else {
      return throwError('Valid token not returned');
   }
});

ou de façon plus concise:

this.httpPost.pipe(switchMap(res => (res.bearerToken) ? 
                                    of(this.saveJwt(res.bearerToken)) : 
                                    throwError('Valid token not returned')
));

Le comportement sera le même, c'est juste une syntaxe différente.

Vous êtes littéralement dire "switch" http observables dans le tuyau à un autre observable, ce qui est tout 'habillage' la valeur de sortie, ou une nouvelle "erreur" observables.

N'oubliez pas de mettre of ou vous aurez de confusion des messages d'erreur.

Aussi la beauté de la 'switchMap' est que vous pouvez revenir à une toute nouvelle "chaîne" de commandes si vous voulais - quelle que soit la logique qui doit être fait avec saveJwt.

7voto

christo8989 Points 2303

Même si cette question a déjà trouvé une réponse, j'aimerais partager ma propre approche (même si elle n’est que légèrement différente de la précédente).

Je déciderais ce qui est renvoyé séparément du mappage et vice versa. Je ne sais pas quel opérateur est le meilleur pour cela, alors je vais utiliser tap .

 this.httpPost.pipe(
  tap(res => { 
    if (!res.bearerToken) {
      throw new Error('Valid token not returned');
    }
  }),
  map(res => this.saveJwt(res.bearerToken)),
);
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X