Je veux lancer une erreur de l' opérateur cartographique de mon observable en fonction d'une condition. Par exemple, si les données API correctes ne sont pas reçues. Veuillez consulter 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 voir dans le code, si la réponse (objet res) n'a pas 'bearerToken', je veux jeter une erreur. Ainsi, dans mon abonnement, il entre dans le 2ème paramètre (handleError) mentionné ci-dessous.
.subscribe(success, handleError)
Aucune suggestion?
angular
typescript
rxjs
Hassan
la source
la source
throw 'Valid token not returned';
?return throw 'message here'
mais fonctionne sans lereturn
mot clé Laissez-moi vérifier si cela fonctionne correctement logiquement.subscribe
méthode et le.finally()
dans le flux se déclenche également. (Cependant, l'exécution est arrêtée, ce qui est une bonne chose)Réponses:
Jetez simplement l'erreur dans l'
map()
opérateur. Tous les rappels dans RxJS sont encapsulés avec des blocs try-catch afin qu'ils soient interceptés puis envoyés en tant queerror
notification.Cela signifie que vous ne retournez rien et lancez simplement l'erreur:
map(res => { if (res.bearerToken) { return this.saveJwt(res.bearerToken); } else { throw new Error('Valid token not returned'); } })
Le
throwError()
(ancienObservable.throw()
dans RxJS 5) est un observable qui envoie simplement uneerror
notification maismap()
ne se soucie pas de ce que vous retournez. Même si vous renvoyez un observable,map()
celui-ci sera transmis commenext
notification.Dernière chose, vous n'avez probablement pas besoin d'utiliser
.catchError()
(anciennementcatch()
dans RxJS 5). Si vous devez effectuer des effets secondaires lorsqu'une erreur se produit, il est préférable d'utilisertap(null, err => console.log(err))
(anciennementdo()
dans RxJS 5) par exemple.Janvier 2019: mise à jour pour RxJS 6
la source
return
l'objet d'erreur et maintenant cela fonctionne parfaitement :) Merci!catch()
que pour enregistrer et renvoyer l'erreur, ce qui n'est pas nécessaire si vous voulez juste effectuer un effet secondaire (journalisation de l'erreur) et il est plus facile à utiliser justedo()
return throwError(new Error('Valid token not returned'));
?return throwError()
retourne anObservable<never>
, cela interrompt immédiatement le flux observable, sans aucun retour.Si vous sentez que cela
throw new Error()
semble inobservable, vous pouvez utiliserthrowError(...)
avecswitchMap
au lieu demap
(la différence étantswitchMap
renvoie une nouvelle observable):// this is the import needed for throwError() import { throwError } from 'rxjs'; // RxJS 6+ syntax this.httpPost.pipe(switchMap(res => { if (res.bearerToken) { return of(this.saveJwt(res.bearerToken)); } else { return throwError('Valid token not returned'); // this is } });
ou plus brièvement:
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 dites littéralement «basculer» de l'observable http dans le tube vers une autre observable, qui consiste soit simplement à «encapsuler» la valeur de sortie, soit à une nouvelle observable «erreur».
N'oubliez pas de mettre
of
ou vous obtiendrez des messages d'erreur déroutants.La beauté de «switchMap» est également que vous pouvez renvoyer une toute nouvelle «chaîne» de commandes si vous le souhaitez - quelle que soit la logique dont vous avez besoin
saveJwt
.la source
switchMap
à uneif
déclaration asynchrone - les choses avaient beaucoup plus de sens :-)Même si cette question est déjà répondue, j'aimerais partager ma propre approche (même si elle n'est que légèrement différente de celle ci-dessus).
Je déciderais de ce qui est renvoyé séparément du mappage et vice versa. Je ne sais pas quel opérateur est le meilleur pour cela, je vais donc l'utiliser
tap
.this.httpPost.pipe( tap(res => { if (!res.bearerToken) { throw new Error('Valid token not returned'); } }), map(res => this.saveJwt(res.bearerToken)), );
la source
tap
est ignorée. ce code fait une chose différente de ce qu'il ditthrow new Error()
est la meilleure option jusqu'à présent