在服务中重构Angular 4 http调用并包含错误

时间:2017-10-31 21:20:15

标签: angular rxjs

我并不完全了解rxjs的内容,所以这可能只是我所知道的差距。

我想将一些我的http内容重构成一个服务。目前我有这个......

this.http.get<LicenseKeyAndUsageModel>('api/license').subscribe(data => {
    this.licenseKeyAndUsage = data;
}, (error: HttpErrorResponse) => {
    if (error.status !== 404) {
        //omitted for brevity, essentially notifies of unknown error.
    }
});

要澄清一下,如果返回404,则表示没有现有的许可证密钥,这很好,因为我的本地变量从未设置过,每个人都很高兴。

但是,现在我想把它重构成一个服务。我看到的大多数示例都显示返回'get'并让调用者订阅结果。

return this.http.get<LicenseKeyAndUsageModel>('api/license');

听起来不错。

我不明白的是如何在服务中包含错误,以便调用者获取值或null。因此,我可以简单地将结果再次分配给局部变量,并让数据绑定完成其余的工作。

我已经看到了类似的东西的一些例子,建议传递一个回调,映射到订阅CompletionObserver,但这对我来说不好闻。

我怀疑答案可能是使用map和catch,但是我不能使用带有catch的HttpErrorResponse,这看起来很羞耻......

return this.http.get<LicenseKeyAndUsageModel>('api/license')
      .map(data => { return data; })
      .catch((error: HttpErrorResponse) => {

      });

(。不允许捕获行,签名错误)

等待明显的答案:)

4 个答案:

答案 0 :(得分:3)

您收到有关错误签名的TypeScript错误的原因是因为catch的实施需要返回新的Observable。根据您所显示的内容,问题实际上是您的void返回类型。

为了重新抛出错误,您可以使用Observable.throw,例如:

return Observable.throw(err);

否则,当您想忽略错误时,您可以使用类似Observable.empty的内容,例如:

return Observable.empty();

要使用Observable.empty,您可能需要添加以下内容:

import 'rxjs/add/observable/empty';

如果您想在使用catch时返回不同的内容,可以使用Observable.of。 e.g:

return Observable.of(null); // Or...
return Observable.of(/* Create your own LicenseKeyAndUsageModel here */);

Observable.of中使用的值将被传递,从而使您的订阅者免于首先发生错误的事实。

同样,要使用Observable.of,您可能需要添加以下内容:

import 'rxjs/add/observable/of';

答案 1 :(得分:0)

如果我能正确理解你的问题你可以做错误处理。

无论您调用哪种方法,订阅时都会执行以下操作。

const myResponse = someHttpService.getLicenseAndModel().subscribe(result => {
  return result,
  return error,
  return complete});

答案 2 :(得分:0)

使用.catch是非常好的解决方案。您错过的是error类型为any。这就是打字稿抱怨签名错误的原因。

return this.http.get('api/license')
  //.map(data => { return data; }) //this is not needed, 
  // you may transform JSON string to actual object here:
  .map(response => response.json())
  .catch((error: any) => {
    // Be aware, that error may be something different than HttpResponse (for example instance of Error or even string).
    // For example, if .json() above would fail, you will get instance of Error class (the one built in JS engine).
    // You may cast error to desired class here.
    if(error instanceof HttpResponse && (error as HttpResponse).status == 404) {
      // Handle this error as you wish here.
    }
    return Observable.throw(error);
  });

另请注意Http服务返回冷Observable。这意味着,在您订阅返回的observable之前,不会发出HTTP请求。

<强>参考HttpResponse个文档: https://angular.io/api/common/http/HttpResponse

添加.catch运算符的方式: https://github.com/ReactiveX/rxjs/blob/master/src/add/operator/catch.ts#L10

.catch的实际定义: https://github.com/ReactiveX/rxjs/blob/master/src/operator/catch.ts#L64

答案 3 :(得分:-1)

老实说,您可能只想改变您的设计。 404错误通常并不意味着服务器没有找到数据,这意味着您未经授权访问给定的URL。你为什么不简单地返回null?

也许我不完全理解你的问题?