简体   繁体   中英

Value undefined when accessed out of observable subscription

I'm trying to get a value outside of subsciption in vain. The value is undefined. Kindly assist.

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
           )
         }

subscribe functions are async so the console log outside of the subscribe function is actually called before your subscribe finishes. You can call all the code you need inside the subscribe method to handle it properly. You can also just do everything inside the subscibe method to. If you need your data to display in the HTML you can just use the repo variable you created as the HTML will update and have access to the repo var when the subscribe method gets called and sets the var inside it.

Typescript

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 or Doesn't make sense: You're basically calling an async function and your hitting race conditions as when your waiting for the code to finish executing your also trying to access a variable that hasn't been defined yet cuz the async function hasn't finished. There are a few different ways to handle that but the easiest and most common solution is to just call functions or manipulate the data inside the subscribe method as it will be defined in there. For more information on subscribe methods or observables check the angular docs or this doc for http methods or this doc for routers

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

This is a lamda method it will be called when data will be fetched successfully, So its make sense that you wont get data before that and your variable will be undefined before this method is called, you can set a default value to the variable so it will be defined in your class

repos = new Array<any>

If this is to display the repos in a component, embrace using rxjs streams and the async pipe. Your code will be shorter and you won't have to worry about subscriptions.

Below is an example of how I would do it based on your code. As you can see I get rid of the need of having ngOnInit method where a subscription is made. Instead, I just create one instance of a readonly a stream that will be used to return repos any time the route params change. This last bit is advantageous over your current method if the component doesn't change when the route does.

Component

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM