HTTP错误处理如何与observable一起使用?

cod*_*leb 21 angular-http angular angular-observable

我看到很多教程做了这样的事情:

http.get("...").subscribe(
  success => console.log('hello success'),
  error => console.log('bye error')
);
Run Code Online (Sandbox Code Playgroud)

我不知道它是如何工作的,因为没有任何类型或任何东西,但是我试图自己这样做,我最终得到请求总是成功,即使我有一个错误.问题是什么?

麻烦制造者:

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)
      );
Run Code Online (Sandbox Code Playgroud)

memberService中的Create-Method:

  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')));
  }
Run Code Online (Sandbox Code Playgroud)

我甚至发现错误,但这subscribe部分似乎并不在意.它失败了success.json(),因为如果有错误,则没有json.但如果出现错误,我希望它可以调用error =>...而不是success.任何建议都非常感谢.

SrA*_*Axi 15

我认为问题在于你不是throwing错误Observable.throw(errMsg).

所以,你可以像这样使用它:

.catch((error:any) => Observable.throw(error.json().error || 'Server error'));
Run Code Online (Sandbox Code Playgroud)

在你的例子中:

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'))));
  }
Run Code Online (Sandbox Code Playgroud)

但是,您可以使用错误处理程序,就像Angular 在此处提出的那样:

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);
  }
Run Code Online (Sandbox Code Playgroud)

所以,你的方法看起来更像是这样的:

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);
  }
Run Code Online (Sandbox Code Playgroud)

对于您可能在服务中创建的其他方法,它实际上更清晰,更可重用.

我建议使用一个响应处理程序,就像Angular的开发人员使用的那样:this.extractData.

很明显,在错误句柄方法中你可以放置自己的自定义逻辑,取决于你想要显示或处理错误的方式.

注意:我没有测试您的代码或我在此处发布的代码.但我想展示/表达这个概念.你应该抛出错误,以免success每次都进入.你如何处理它取决于你和你的应用程序.

  • @TrudleR我发现了这个:https://xgrommx.github.io/rx-book/content/getting_started_with_rxjs/creating_and_querying_observable_sequences/error_handling.html我会珍惜它并阅读它几次,我发现它非常有用.如果您注意到,当未处理或抛出错误时,即使错误/失败,您也会按原样接收数据. (2认同)