web-dev-qa-db-de.com

Wie funktioniert die HTTP-Fehlerbehandlung bei Observablen?

Ich sehe viele Tutorials, die so etwas tun:

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

Ich weiß nicht, wie das funktioniert, da es keine Typen oder ähnliches gibt jedoch Ich habe versucht, das selbst zu tun, und am Ende ist die Anfrage immer erfolgreich, auch wenn ich eine habe Error. Was ist das Problem?

nruhestifter:

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-Methode im memberService:

  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')));
  }

Ich verstehe sogar den Fehler, aber der Teil subscribe scheint es nicht zu interessieren. Es schlägt bei success.json() fehl, da im Fehlerfall kein json vorhanden ist. Aber wenn es einen Fehler gibt, möchte ich, dass er den error =>... Anstelle des success aufruft. Jeder Rat wird sehr geschätzt.

21
codepleb

Ich denke, das Problem ist, dass Sie nicht throwing der Fehler mit einer Observable.throw(errMsg) sind.

Sie können es also einfach so verwenden:

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

In deinem Beispiel:

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'))));
  }

Sie können jedoch einen Fehlerbehandler wie den folgenden verwenden: Angular proposes here :

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);
  }

Und so würde Ihre Methode ungefähr so ​​aussehen:

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);
  }

Es ist tatsächlich sauberer und wiederverwendbarer für andere Methoden, die Sie möglicherweise in Ihrem Service erstellen.

Ich würde vorschlagen, auch einen Response-Handler zu verwenden, wie er von Angulars Entwicklern verwendet wird: this.extractData.

Natürlich können Sie innerhalb der Fehlerbehandlungsmethode Ihre eigene benutzerdefinierte Logik einfügen, je nachdem, wie Sie den Fehler anzeigen oder behandeln möchten.

HINWEIS: Ich habe weder Ihren Code noch den hier veröffentlichten Code getestet. Aber ich wollte das Konzept zeigen/ausdrücken. Sie sollten den Fehler auslösen, um nicht jedes Mal in success zu wechseln . Wie Sie damit umgehen, hängt von Ihnen und Ihrer App ab.

15
SrAxi

Für mich geht das:

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