0

I'm trying to call a function from a 5-deep nested function in Typescript, and it's not able to see the outside function. Running console.log(this) inside of setTimeout returns the window object.

export class SearchComponent implements OnInit {


lifeCycleFunc(){    //Function 1
    ...

    if() {                //Function 2
        ....

        var.do(item => {        //Function 3
            ....

            var.forEach(var => {      //Function 4
                ...

                setTimeout(function(){    //Function 5

                    this.searchFunc()        //this.searchForAssignments is not a function
                }
            })
        })
    }
}

searchFunc(){
    ...
}


}
2
  • Is this in a class? If so can we see the context of that class or if not then just drop the ‘this’ in front of searchFunc Commented Nov 11, 2017 at 4:40
  • Yes, this is in a class. I updated my code. Commented Nov 11, 2017 at 4:41

3 Answers 3

1

this context inside setTimeout callback is going to be global object (window), but it should be SearchComponent class for this code to work correctly. To achieve that all nested functions including setTimeout callback should be arrow functions to bind this context correctly:

export class SearchComponent implements OnInit {    
    lifeCycleFunc(){
        ...

        if(condition) {
            ...

            foo.do(bar => {
                ...

                bar.forEach(baz => {
                    ...

                    setTimeout(() => {  
                        this.searchFunc();
                    }, 0);
                });
           });
       }
    }

    searchFunc(){
      ...
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

All my callbacks are already using arrow functions like you show. Running console.log(this) inside of setTimeout returns the window object for me.
@FiringBlanks Function 5 in your question is not an arrow function
The setTimeout is not an arrow function? How would I make it one then?
1

To answer your question and your comment about making it an arrow function, you do this:

setTimeout(() => {  
    this.searchFunc();
}, 0);

instead of:

setTimeout(function() {  
    this.searchFunc();
}, 0);    

3 Comments

If you want to answer on a comment, you must set it as a comment under the one you are answering on it, because this is not an answer on the original question.
Yea well I can't add a comment because I don't have 50 rep, which is an absurd restriction. Oh and it does actually answer the question.
Ok, but the way you are answering is thought to be on the comment. However you can edit it to make it answering clearly the original question.
0
var.forEach(var => {    //Function 3
            ...

            this.searchFunc()     //TypeError: this.searchForAssignments is not a function
        }.bind(this))

The this reference inside the forEach is the forEach function. You need to bind it to the this reference of the class.

4 Comments

it says 'cannot find name bind'. Do I have to import it from somewhere?
Oh wait that might not work on a lambda....... *sorry on my phone here. You wouldn’t need to import bind.
Are u by chance calling this like a static method? Like SearchSchoolComponent.lifeCycleFunc() ??
Nope, I was typing feverishly until I hit the not a function error on that very line. I'm not referencing this whole class from anywhere else.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.