web-dev-qa-db-fra.com

Dans Angular2, comment intercepter la réponse d'erreur observable et la transmettre au canal d'erreur

J'ai un service qui interagit avec un serveur api. Il a la méthode myHttpPost (data). Cette méthode devrait:

  1. appeler le http.post d'Angular sur le serveur
  2. si la réponse a le statut 200, fournissez le contenu json de la réponse à l'abonné
  3. si la réponse a un état différent, traiter la réponse et fournir une erreur traitée à l'abonné

La version actuelle de ma méthode est:

postData(path: string, data: Object): Rx.Observable<any> {
    let json = JSON.stringify(data);
    return this.http.post(path, json)
        .map(res => res.json())
}

Cela ne fait pas le point 3 de la liste ci-dessus, car la carte n'est appelée qu'en cas de succès et non en cas d'erreur. Je pourrais changer la séquence en ajoutant:

.catch(error => {
    let myError = prepareErrorContent(error);
    return Rx.Observable.throw(myError);
});

Ensuite, l'abonné (un autre service) reçoit myError (c'est ok) mais la documentation de rxjs dit ce qui suit à propos de la méthode catch (): "Continue une séquence observable qui se termine par une exception avec la séquence observable suivante." = Mais je veux que la séquence se termine normalement et ne continue pas. Si j'utilise la catch() comme ci-dessus, le prochain appel à postData () de l'abonné ne fonctionne pas (il renvoie immédiatement la même erreur au lieu de faire l'appel http). Je pense que c'est parce que la séquence n'est pas terminée.

Comment faire?

[Modifier] Ceci est ma méthode d'abonné qui utilise ce service:

 this.jsonHttp.postData(path, data)
    .subscribe(
        struct => onNext(struct),
        error => {
            let message = this.jsonHttp.extractError(error);
            onError(message)
        },
        () => onComplete ? onComplete() : null
    );
11
camcam

En effet, pour chaque requête HTTP une chaîne de traitement est créée et exécutée. Lorsque la réponse est reçue (à la fois avec succès et avec erreur), la chaîne est terminée.

Si vous exécutez deux fois la demande, il n'y a aucun lien entre eux. Vous pouvez avoir des liens lorsque les deux demandes font partie de la même chaîne de traitement. Par exemple, lorsque vous utilisez des opérateurs observables comme flatMap ou switchMap. Voici un exemple:

return this.http.get(...)
        .map(res => res.json())
        .flatMap(jsonData => {
          // Can leverage the result of the previous request 
          return this.http.get(...).map(res => res.json());
        });

Lorsqu'une erreur se produit, la chaîne de traitement est rompue et l'opérateur catch est appelé. Vous pouvez renvoyer un observable dans le rappel associé pour continuer la chaîne de traitement. Il peut s'agir d'une observation classique ou d'une erreur avec Observable.throw. Dans le cadre d'une requête HTTP dans Angular2, une réponse avec un code d'état différent de 2xx est considérée comme une erreur.

Au retour Observable.throw, le deuxième rappel spécifié lors de l'abonnement est appelé. Si c'est un autre observable, le premier rappel est appelé. Par exemple:

return this.http.get(...)
        .map(res => res.json())
        .catch(res => {
          // The error callback (second parameter) is called
          return Observable.throw(res.json());
          // The success callback (first parameter) is called
          // return Observable.of(res.json());
        });

J'ai implémenté un plunkr qui exécute une demande (en cliquant sur un bouton) sans en-tête d'authentification, donc un code d'état 401 est reçu. Lorsque vous cliquez à nouveau, l'en-tête est ajouté, donc un code d'état 200 est reçu. Juste pour vous montrer qu'il n'y a pas de relation entre les deux demandes.

Voir ce plunkr: https://plnkr.co/edit/5WwWpwjvQmJ4AlncKVio?p=preview .

18
Thierry Templier