在嵌套组件中使用时,服务为空

问题描述 投票:-2回答:2

注入的服务在嵌套组件中为null。如何在嵌套组件中使用服务

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(...)未定义

angular
2个回答
0
投票

请确保AccountService位于您正在使用的模块的providers数组中或应用程序的app.module中。在最新情况下,您还可以执行

@Injectable({
  providedIn: 'root'
})
export class AccountService {....}

这将在app.module中自动注入服务,因此您无需手动将其添加到提供程序。


0
投票

Önay,如果您有专门的服务,您会喜欢的

getUser(user)
{
     return this.HttpClient.get('....'+user)
}

返回可观察值

如果有喜欢的话

**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。>

注意2:记住,优良作法:“服务返回Observables,组件从属于服务”

© www.soinside.com 2019 - 2024. All rights reserved.