angular - 在嵌套组件中使用时服务为空
问题描述
在嵌套组件中注入的服务为空。如何在嵌套组件中使用服务
export class ActivityComponent implements OnInit {
constructor(
.
.
public accountService: AccountService //it is null when use in view!!!!
) { }
....
}
<app-some-component>
...
<div *ngFor="let task of tasksService.bindingSource.dataSource">
<app-activity [task]="task"></app-activity>
</div>
...
</app-some-compnent>
<div>{{accountService.getUser(task.userId).name}}</div> <!-- <= error line -->
错误:_co.accountService.getUser(...) 未定义
解决方案
Önay,如果你有一个典型的服务,你会有一些像
getUser(user)
{
return this.HttpClient.get('....'+user)
}
返回一个 Observable
如果你有一些喜欢
**example of WRONG service
user:any
getUser(user)
{
this.HttpClient.get('....'+user).subscribe(res=>{
this.user=res
}
return this.user //<---here user is null because we are making
//async call
}
好吧,你明白为什么 getUser 在最后一种情况下返回 null 而在第一种情况下你不能使用 accountService.getUser().value。accontService
不为 null,但 accountService.getUser()返回 null。
让我解释一下如何解决有关您需要获取accountService数据的问题。
您可以采用两种方法,获取用户列表,然后获取任务列表并使用用户的值映射 las 列表。我们需要使用 switchMap 和 map 'rxjs' 操作符
想象一下,你有
getUserList(): Observable<User[]> {
return this.httpClient.get<User[]>("..."); //get an array of Users
}
getTaskList(): Observable<Task[]> {
return this.httpClient.get<Task[]>("..."); //get an array of Tasks
}
您可以创建一个新方法,该方法返回带有用户名的任务列表
getTaskExtenderList(): Observable<any[]> {
return this.getUserList().pipe(
switchMap((users: any[]) => {
//in users we has the list of users, but we want
//return the task
return this.getTaskList().pipe(
map((task: any[]) => {
//here we has the list of task
task.forEach(x => {
const user = users.find(u => u.userId == x.userId);
x.userName = user ? user.userName : null;
});
return task;
})
);
})
);
}
另一种方法是,对于每个任务,创建对用户的调用并将名称加入任务(这种方法是当用户列表非常大并且每个用户有一个或两个任务时)
//we has a function
getUser(userId): Observable<User> {
return this.httpClient.get<User>("....."+userId)
}
getTaskExtenderList2(): Observable<any[]> {
return this.getTaskList().pipe(
map((tasks: Task[]) => {
const users = tasks.map((t: Task) => t.userId);
const obs = users
.filter((x, index) => users.indexOf(x) == index)
.map(u => this.getUser(u));
return { uniqueUsers: obs, tasks: tasks };
}),
switchMap((data: { uniqueUsers: Observable<User>[]; tasks: any[] }) => {
return forkJoin(data.uniqueUsers).pipe(
map((users: any[]) => {
data.tasks.forEach(t => {
const user = users.find(u => u.userId == t.userId);
t.userName = user ? user.userName : null;
});
return data.tasks;
})
);
})
);
}
好吧,你在stackblitz中有两种方法
注意:在stackblitz中我使用“of”来模拟httpClient.get
NOTE2:记住一个好的做法:“服务返回 Observables,组件订阅服务”
推荐阅读
- c# - 如何动态更改我在 MVVM XAML 中使用的控件
- ios - 适合多级/屏幕游戏的场景套件架构
- file - UWP 打开文件问题
- excel - 函数属性数据透视表类
- date - 如何在一个应用程序中连贯地使用 RRULE 日期时间序列和任意的非 RRULE 日期时间序列
- android - Android 10:IMEI 在 API 29 上不再可用。寻找替代品
- java - 当我加载 openSourceBim IfcModelService 时,它总是为空
- ios - Xcode 11 无法将 Info.plist 重新分配到一个组中
- prisma - 使用 nexus 在 Prisma2 中公开总页数的最佳方法是什么?
- amazon-web-services - 如何找到离特定网站最近的 EC2 可用区