web-dev-qa-db-fra.com

Comment la gestion des erreurs HTTP fonctionne-t-elle avec les observables?

Je vois beaucoup de tutoriels faisant quelque chose comme ça:

http.get("...").subscribe(
  success => console.log('hello success'),
  error => console.log('bye error')
);

Je ne sais pas comment cela fonctionne, puisqu'il n'y a pas de types ou quoi que ce soit, cependant J'ai essayé de le faire moi-même et je finis par dire que la demande aboutit toujours au succès, même si j'ai un Erreur. Quel est le problème?

Troublemaker:

this.memberService.create(this.currentMember)
      .subscribe(
        success => {
          let mem: Member = success.json() as Member;
          if (this.selectedOrganization) {
            this.addMemberToOrganization(mem);
          } else if (this.selectedServiceProvider) {
            this.addMemberToServiceProvider(mem);
          } else {
            this.toastsService.error("lbl_users_service_provider_and_organization_undefined");
          }
        },
        error => console.log(error)
      );

Create-Method dans le service de membre:

  create(member: Member): Observable<any> {
    return this.http
      .post(this.RESOURCE_BASE_URL, member)
      .map(response => {
        if (response.status === 200) this.toastsSerivce.success(this.translateService.instant('lbl_users_member_created'));
        return response;
      })
      .catch(error => this.toastsSerivce.error(this.translateService.instant('lbl_users_member_create_failed')));
  }

J'ai même attrapé l'erreur, mais la partie subscribe ne semble pas s'en soucier. Il échoue à success.json(), car s'il y a une erreur, il n'y a pas de json. Mais s'il y a une erreur, je veux qu'il appelle le error =>... À la place du success. Tout conseil est fortement apprécié.

21
codepleb

Je pense que le problème est que vous n'êtes pas throwing l'erreur avec un Observable.throw(errMsg).

Donc, vous pouvez simplement l'utiliser comme ceci:

.catch((error:any) => Observable.throw(error.json().error || 'Server error'));

Dans votre exemple:

create(member: Member): Observable<any> {
    return this.http
      .post(this.RESOURCE_BASE_URL, member)
      .map(response => {
        if (response.status === 200) this.toastsSerivce.success(this.translateService.instant('lbl_users_member_created'));
        return response;
      })
      .catch((error:any) => Observable.throw(this.toastsSerivce.error(this.translateService.instant('lbl_users_member_create_failed'))));
  }

Mais, vous pouvez utiliser un gestionnaire d’erreur, comme celui Angular propose ici :

private handleError (error: Response | any) {
    // In a real world app, you might use a remote logging infrastructure
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
  }

Et alors, votre méthode ressemblerait plus à ceci:

create(member: Member): Observable<any> {
    return this.http
      .post(this.RESOURCE_BASE_URL, member)
      .map(response => {
        if (response.status === 200) this.toastsSerivce.success(this.translateService.instant('lbl_users_member_created'));
        return response;
      })
      .catch(this.handleError);
  }

C'est en fait plus propre et plus réutilisable pour d'autres méthodes que vous pouvez créer au sein de votre service.

Je suggérerais d'utiliser également un gestionnaire de réponses, comme celui utilisé par les développeurs d'Angular: this.extractData.

De manière évidente , dans la méthode de traitement des erreurs, vous pouvez insérer votre propre logique personnalisée , selon la façon dont vous souhaitez afficher ou gérer l'erreur.

REMARQUE: Je n'ai pas testé votre code ni le code que j'ai posté ici. Mais je voulais montrer/exprimer le concept. Vous devriez jeter l'erreur afin de ne pas entrer dans success à tout moment . Comment vous gérez cela dépend de vous et de votre application.

15
SrAxi

Ça marche pour moi:

this.http.post('http://example.com/path/', {sampleData: 'd'}).subscribe(
res => {alert('ok!');},
err => alert(err.error)
)
0
yaya