'This' is undefined inside subscribe

Viewed 5120

I have a subscribe statement and I am trying to debug this however when I step through in VS Code 'this' is always undefined inside the statement. In this situation 'this.dataLoaded' is undefined. how can I get it to not be undefined when debugging?

this.router.events
            .filter(event => (event instanceof NavigationEnd))
                .subscribe((routeData: any) => {                        
                    if(!this.dataLoaded){
                      ...
                    }
                });  
5 Answers

Please have a look on closure expand sections in debugger variables tab. Your real this will be one level above the top-most, where this is referred to component controller name. Each anonymous function creates additional closure, in your case it's enclosed in subscribe, ant this closure will be opened by default by VS Code when your breakpoint will be hit.

And please try to avoid this old-style JS hacking let that = this e.c.t, because when you on TypeScript, Classes, ES6 and arrow functions those hacks are just not needed anymore.

When you are using .subscribe() then in angular it may possible that it'll not getting this. In my case I used another replica of this. It always works for me. It may for you also.

var that = this; // Hear I store the this ref into another that
this.router.events
        .filter(event => (event instanceof NavigationEnd))
            .subscribe((routeData: any) => {                        
                if(!that.dataLoaded){  // Hear you can use that instead of this
                  ...
                }
            }); 

I'm not sure this is a good idea or not. I'm a beginner. but You could use the .bind(this) method.

here is an angular ts example:

this.myService.getData().subscribe((data=>{
    this.doSomething(data);
    alert(this.somethingElse);
}).bind(this));

As someone who was close to implementing the that = this route from the accepted answer, save yourself and look into the answer Tomas wrote. It's good to spend some extra time on and to avoid using javascript hacks if possible.

For an example in using arrow functions to keep your this context, see below.

This is the code I originally had which lost the this context:

this.settingsService.getClientSettingsByCategory(clientId, categoryId)
    .subscribe(
        this.loadJobStatusReport
    );

And this is the updated code which keeps the expected this context:

this.settingsService.getClientSettingsByCategory(clientId, categoryId)
    .subscribe(
        settings => this.loadJobStatusReport(settings)
    );

I figured out that it makes a huge difference between

a.subscribe(function(x){ ... }) // <-- here this is bound to a

and

a.subscribe(x => { ... }) // <-- here this is the class where we're in

So I use the second one all the time and thus don't need to use something like var self = this

Related