Angular 5-如何在http调用中链接观测值?

Angular 5-如何在http调用中链接观测值?,angular,typescript,observable,Angular,Typescript,Observable,我正在用Angular 5编写一个应用程序,我希望在自己的服务中保留原始http调用,以便其他服务可以根据需要操纵响应。 例如,我将有一个组件、组件服务和组件数据服务 我如何将我的观察值与此模式联系起来?以下是我尝试过的: licenseData.service.ts import { Injectable } from '@angular/core'; import { HttpClient, HttpParams, HttpErrorResponse } from '@angular/com

我正在用Angular 5编写一个应用程序,我希望在自己的服务中保留原始http调用,以便其他服务可以根据需要操纵响应。 例如,我将有一个组件、组件服务和组件数据服务

我如何将我的观察值与此模式联系起来?以下是我尝试过的:

licenseData.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpParams, HttpErrorResponse } from '@angular/common/http';
import { CONSTANT } from '../../environment/constants';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/throw';

@Injectable()
export class LicenseDataService {

    constructor(private http: HttpClient) {}

    getLicenseInfo() {

        const params = new HttpParams()
            .set('unsername', 'swapp')
            .set('comment', "hi");

        const endpoint = '/myendpoint';

        return this.http
            .get(endpoint, {params: params})
            .map((response) => {
                console.log(' response ', response);
                //return Observable.of<any>(response);
                return response['data'];
            })
            .catch(this.errorHandler);
    }

    errorHandler(error: HttpErrorResponse) {
        //TODO: log the error here
        return Observable.throw(error);
    }

}
import { Injectable } from '@angular/core';
//import { Observable } from 'rxjs/Observable';
import { LicenseDataService } from './licenseData.service';

@Injectable()
export class LicenseService {

    constructor(private licenseDataService: LicenseDataService) { }

    getVersion() {

        //handle the error in here and the loading as well

        return this.licenseDataService.getLicenseInfo()
            .subscribe((response) => {
                return response['versionNumberField'];
            });
        //console.log(' result ', result);

        //return result['versionNumberField'];
    }

}
这是我的部分组件代码:

export class AboutComponent implements OnInit {

    //version: Observable<string>;
    version: string;

    constructor(private licenseService: LicenseService) {
        console.log('Hello Component');
    }

    ngOnInit() {
        console.log('ngOnInit');

        //this.version = this.licenseService.getVersion();

        this.licenseService.getVersion()
           .subscribe(response => this.version = response);
    }

}
export类AboutComponent实现OnInit{
//版本:可观察;
版本:字符串;
构造函数(专用许可证服务:许可证服务){
log('Hello Component');
}
恩戈尼尼特(){
console.log('ngOnInit');
//this.version=this.licenseService.getVersion();
此.licenseService.getVersion()文件
.subscribe(response=>this.version=response);
}
}

我的项目无法构建。如何正确链接此对象?

您无法订阅Subscribtion对象

你有这个密码 许可证数据服务:

return this.licenseDataService.getLicenseInfo()
            .subscribe((response) => {
                return response['versionNumberField'];
            });
在LicenseService中,您尝试订阅LicenseDataService返回的已经是订阅的内容。其中一个选项是在LicenseService中使用
map
,然后在组件中订阅

  return this.licenseDataService.getLicenseInfo()
            .map((response) => {
                return response['versionNumberField'];
            });
在此之后,您的
subscribe
in组件应该可以工作


我个人会使用一种服务,这些操作并没有那么复杂。

除非您必须这样做,否则您不希望在服务内部管理订阅

如果我是你,我会将HTTP服务公开为可观察的,并使用共享重播,以便在应用程序的整个生命周期中订阅appVersion时共享结果。这样,您的服务内部就没有内部订阅,这是一种代码气味

    @Injectable()
    export class LicenseService {


          private _appVersion$;

          get appVersion$(){
              if(!this_appVersion$){
                this._appVersion$ = this.getVersion().pipe(shareReplay());   
              }
              return this._appVersion$;
          }

          private getVersion() {

        //handle the error in here and the loading as well

            return this.licenseDataService.getLicenseInfo()
               .pipe(
                  map(response => return response['versionNumberField'] as any
               );
         }     
   } 
然后在您的组件中,您可以注入服务并订阅appVersion$observable以获取应用程序版本值


我之所以这样做,是因为它将一切都保持在一个更具反应性的编程范式中,并允许您将动作与其他异步代码链接在一起。在您的
LicenseService
中,
map()
而不是
subscribe()
我的最终结果是否需要是一个可观察的值?值没有更新?我不确定您的意思。您能解释更多吗?我如何在代码中使用类似“finally”的内容?文档说finally在Observable上不存在。我用管道尝试了这一点,它给了我以下错误:this.licenseService.getWebwiseVersion()L27:.subscribe((response)=>{console.log(response);this.webwiseVersion=response;});类型“{}”不可分配给类型“Observable”。类型“{}”中缺少属性“\u isScalar”。我进行了几次更新,首先我忘记添加将所有属性绑定在一起的shareReplay操作符,其次我更新了映射,使其将输出强制转换为any,这将修复编译器错误。如果您可以访问属性
response.versionNumberField
而不是
response['versionNumberField']
,我会这样做,这样它就有了更好的打字支持您想用'finally'做什么?看看angular.io文档。特别是Heros演示应用程序()。您可以看到,我们在组件中订阅,并在服务中执行所有其他操作。根据样式指南,您应该在服务中完成所有的数据操作/映射,所以我将试一试并称之为良好实践。特别是如果您希望使用LicenseService/LicenseDataService。我个人会使用一个服务-这些操作没有那么复杂,我希望有两个服务,因为我将有错误记录和其他事情发生,我不想膨胀我的其他服务。因此,使用这个单独的服务,我认为这是最好的选择。这似乎不是一个坏习惯。您只需在服务中处理数据,然后在组件中获取它们,这样一切都很好。我可以在这里使用什么作为finally块?只需使用rxjs finally块?我不明白你的担心。