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) 你能详细介绍一下本地状态和异步管道吗?啊,我复制并粘贴了一个我正在处理的项目。更新更新!异步管道只是一个帮助器,它允许您编写更少的代码。我喜欢它胜过本地的