在可观察订阅之外访问时的值未定义

时间:2021-04-02 16:34:34

标签: angular rxjs observable

我试图获得订阅之外的价值是徒劳的。该值未定义。请协助。

repos:Repo[];

constructor(private route:ActivatedRoute, private githubAPIservice:GihubAPIService) {  }
  
ngOnInit(): void {
    this.username = this.route.snapshot.queryParams['username'];

    this.githubAPIservice.getUserRepos(this.username)
        .subscribe(response => { 
                                this.repos = response;
                                console.log(this.repos) //accessible
                             }
                console.log(this.repos) //undefined
           )
         }

3 个答案:

答案 0 :(得分:0)

订阅函数是异步的,因此订阅函数之外的控制台日志实际上在订阅完成之前被调用。您可以在 subscribe 方法中调用您需要的所有代码来正确处理它。您也可以在 subscibe 方法中执行所有操作。如果您需要将数据显示在 HTML 中,您可以使用您创建的 repo 变量,因为当调用 subscribe 方法并在其中设置 var 时,HTML 将更新并可以访问 repo var。

打字稿

constructor(private route:ActivatedRoute, private githubAPIservice:GihubAPIService) {}

ngOnInit(): void {
  this.username = this.route.snapshot.queryParams['username'];

  this.githubAPIservice.getUserRepos(this.username).subscribe(
      response => { 
                   this.repos = response;
                   this.anotherFunctionToHandleRepos();
                  });
}

anotherFunctionToHandleRepos() {
 // do whatever you need to do if you don't need to do anything with the data then your fine. This will be able to access this.repos with the data in it as it will be called after the repos has been set.
}

HTML

{{repos}} <!-- This will show the values assigned in the sub as soon as the code inside the subscribe assigned it to the var repos  -->

TDLR 或 没有意义: 您基本上是在调用异步函数并遇到竞争条件,因为当您等待代码完成执行时,您还尝试访问尚未定义的变量,因为异步函数尚未完成。有几种不同的处理方法,但最简单和最常见的解决方案是在 subscribe 方法中调用函数或操作数据,因为它将在那里定义。有关订阅方法或 observable 的更多信息,请检查 angular docs 或此 doc 用于 http 方法或此 doc 用于路由器

答案 1 :(得分:0)

response => { 
     this.repos = response;
     console.log(this.repos) //accessible
}

这是一个 lamda 方法,它会在数据获取成功时调用,因此在此之前您不会获取数据并且在调用此方法之前您的变量将是未定义的,您可以将默认值设置为变量,因此它将在您的类中定义

repos = new Array<any>

答案 2 :(得分:0)

如果这是在组件中显示存储库,请使用 rxjs 流和异步管道。您的代码会更短,而且您不必担心订阅。

下面是我将如何根据您的代码执行此操作的示例。如您所见,我不需要在进行订阅时使用 ngOnInit 方法。相反,我只是创建了一个只读流的实例,该流将用于在路由参数更改时任何返回存储库。如果组件在路由改变时没有改变,最后一点比你当前的方法更有优势。

组件

constructor(private route:ActivatedRoute, private githubAPIservice:GihubAPIService) {  }

readonly repos$ = this.route.queryParams.pipe(
    switchMap(p => this.githubAPIservice.getUserRepos(p['username'])),
    startWith([]) // optional
  );

HTML

<div *ngFor="let repo of repos$ | asnyc">
   <!-- show stuff -->
</div>