Angular 共享服务变量未定义?

Angular 共享服务变量未定义?,angular,Angular,我有一个具有以下方法的服务: public GetCaseData(){ const url = environment.api_url; const headers = new Headers(); headers.append('Content-Type', 'application/json'); return this._http.get(url, { headers: headers }) .map(response => { return resp

我有一个具有以下方法的服务:

public GetCaseData(){

const url =  environment.api_url;

const headers = new Headers();
headers.append('Content-Type', 'application/json');
return this._http.get(url, { headers: headers })
    .map(response => {
        return response.json();
    });
}
在我的app.component.ts中,我这样称呼它:

  constructor(private _caseService : CaseService) {}

  ngOnInit(): void {

    this._caseService.GetCaseData().subscribe(data => {
      this._caseService.caseData = data;

    });

  }
我想将此.u caseService.caseData共享给我的其他组件
Home
Contact
,但在这些组件中,此.u caseService.caseData未定义。 比如说家

 constructor(private _caseService: CaseService) { }

  ngOnInit() {
    console.log(this._caseService.caseData); //is undefined here because it
                                            // is called before the data comes back
}
我知道原因(因为组件是在数据返回之前初始化的),但我不确定如何修复它

我在家里放了一个getter,我看到了呈现的数据。返回数据后,是否在生命周期的稍后阶段调用getter:

  ngOnInit() {
    this.data = this._caseService.caseData;
    console.log('this.data ', this.data) //undefined
  }

  get caseData()
  {
    return this._caseService.caseData; //data rendered on html page
  }
当我执行以下操作时,它说它需要一个
而不是
数据。
它还抱怨应该有一个
ngOnInit
关闭
}

恩戈尼尼特(){ this.concatCaseData$=this.\u caseService.caseData$.map(数据=>{ 返回{data.OfficialCaseName} }


}您可以在组件中使用getter

//You can use in your .html
//{{caseData}}

get caseData()
{
    return this._caseService.caseData;
}
另一个想法是订阅一个可观察到的服务。
注意:最好使用HttpClient而不是“旧”http,您可以在组件中使用getter

//You can use in your .html
//{{caseData}}

get caseData()
{
    return this._caseService.caseData;
}
另一个想法是订阅一个可观察到的服务。
注意:最好使用HttpClient而不是“旧的”http来添加到Elseo answer,Getter会修复您的问题,因为它经常被调用

另一种选择,我认为是更好的解决方案,是使用BehaviorSubject,因为你可以给它一个初始状态,然后订阅它

例如,您的
案例服务

private caseDataStore = new BehaviorSubject<any>({});
public caseData$ = this.caseDataStore.asObservable();

public GetCaseData(){

const url =  environment.api_url;

const headers = new Headers();
headers.append('Content-Type', 'application/json');
return this._http.get(url, { headers: headers })
    .map(response => {
        return response.json();
    }).toPromise().then(res => {
    caseDataStore.next(res);
});
}
最后,在其他组件上,您只需订阅即可

this._caseService.caseData$.subscribe( res => {
        this.caseData = res;
    }) 

UPDADE:详细说明异步管道

Async pipe非常棒!它是一个方便的助手,允许我们订阅observable而不必担心取消订阅。减少了我代码中的大量锅炉板。要在示例中使用
Async
pipe:

而不是在组件上执行此操作

 this._caseService.caseData$.subscribe( res => {
        this.caseData = res;
 }) 
你可以把它放在你的html中

 <div> {{ _caseService.caseData$ | async }} </div> 
要摆脱这种情况,您可以使用

  <div *ngIf="_caseService.caseData$  | async as caseData">
      <div> {{caseData.prop1}} <div>
      <div> {{caseData.prop2}} <div>
      <div> {{caseData.prop3}} <div>
  </div>
我在服务中使用了
toPromise
,因为这是一个一次性呼叫,不想在之后取消订阅。或者,我看到其他人使用
.first()


更新3:如果您只想对从组件中获得的属性进行选择,您可以
映射
从可观察对象中提取它

假设您已经在contact组件中使用异步管道

public contactCaseData$ = this._caseService.caseData$.map( data => { 
    return {data.prop1, data.prop2}
}
现在像往常一样订阅。如果你想更进一步!你可以在你的应用程序中编写地图管道

import { Pipe, PipeTransform } from '@angular/core';
import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/map";

@Pipe({
  name: 'map'
})
export class MapPipe implements PipeTransform {

  transform(o$, propsNames): any {
    return o$.map(res => {
      return propsNames.reduce((acc, cur) => {
        acc[cur] = res[cur];
        return acc;
      }, {})
    })
  }

}

演示其工作原理:

要添加到Elseo answer中,Getter将修复您不断被调用的问题

另一种选择,我认为是更好的解决方案,是使用BehaviorSubject,因为你可以给它一个初始状态,然后订阅它

例如,您的
案例服务

private caseDataStore = new BehaviorSubject<any>({});
public caseData$ = this.caseDataStore.asObservable();

public GetCaseData(){

const url =  environment.api_url;

const headers = new Headers();
headers.append('Content-Type', 'application/json');
return this._http.get(url, { headers: headers })
    .map(response => {
        return response.json();
    }).toPromise().then(res => {
    caseDataStore.next(res);
});
}
最后,在其他组件上,您只需订阅即可

this._caseService.caseData$.subscribe( res => {
        this.caseData = res;
    }) 

UPDADE:详细说明异步管道

Async pipe非常棒!它是一个方便的助手,允许我们订阅observable而不必担心取消订阅。减少了我代码中的大量锅炉板。要在示例中使用
Async
pipe:

而不是在组件上执行此操作

 this._caseService.caseData$.subscribe( res => {
        this.caseData = res;
 }) 
你可以把它放在你的html中

 <div> {{ _caseService.caseData$ | async }} </div> 
要摆脱这种情况,您可以使用

  <div *ngIf="_caseService.caseData$  | async as caseData">
      <div> {{caseData.prop1}} <div>
      <div> {{caseData.prop2}} <div>
      <div> {{caseData.prop3}} <div>
  </div>
我在服务中使用了
toPromise
,因为这是一个一次性呼叫,不想在之后取消订阅。或者,我看到其他人使用
.first()


更新3:如果您只想对从组件中获得的属性进行选择,您可以
映射
从可观察对象中提取它

假设您已经在contact组件中使用异步管道

public contactCaseData$ = this._caseService.caseData$.map( data => { 
    return {data.prop1, data.prop2}
}
现在像往常一样订阅。如果你想更进一步!你可以在你的应用程序中编写地图管道

import { Pipe, PipeTransform } from '@angular/core';
import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/map";

@Pipe({
  name: 'map'
})
export class MapPipe implements PipeTransform {

  transform(o$, propsNames): any {
    return o$.map(res => {
      return propsNames.reduce((acc, cur) => {
        acc[cur] = res[cur];
        return acc;
      }, {})
    })
  }

}

演示其工作原理:

是的,我昨天刚升级到Angular5,但还没有完成。您能给我一个更详细的getter和订阅示例吗?非常感谢。我很忙,但使用httpClient,您不需要map json。因此,使用Angular5,您不需要转换为承诺使用“do”:返回此.httpClient.get(url).do(res=>{caseDataStore.next(res);})是的,我昨天刚升级到Angular5,但还并没有完成。你们能给我一个关于getter和订阅的更详细的例子吗?非常感谢。我很忙,但使用httpClient,你们不需要map json。所以,使用Angular5,你们不需要转换成承诺,只要使用“do”:返回这个。httpClient.get(url)。do(res=>{caseDataStore.next(res);})谢谢,我有几个问题:1)这个.sidebarStatusStore.AsObservable()是什么?3) 你能详细介绍一下本地状态和异步管道吗?啊,我复制并粘贴了一个我正在处理的项目。更新更新!异步管道只是一个帮助器,它允许您编写更少的代码。我更喜欢它而不是本地州,因为我不必编写取消订阅逻辑。RxJs功能非常强大,如果通过链接您的操作符来正确利用,它通常会将视图层简化为一个订阅。哇,感谢我使用本地状态获得它…我现在要尝试异步。Behavior Subject和Subject之间有什么区别?Behavior Subject处于初始状态,每个订阅将自动获取最后一个值。与subject相反,subject只有在订阅已建立时才有价值。谢谢,我有几个问题:1)这是什么。sidebarStatusStore.AsObservable()?2) 在这个例子中,toPromise做了什么?3) 你能详细介绍一下本地状态和异步管道吗?啊,我复制并粘贴了一个我正在处理的项目。更新更新!异步管道只是一个帮助器,它允许您编写更少的代码。我喜欢它胜过本地的