proximacentauri
proximacentauri

Reputation: 1879

Vuejs access function from nested fuction

I am trying to access a function A from a function in a function in A eg:

functionA () {
    functionB () {
        functionC () {
           #want to call functionA from here
        }
     }
 }

here is the code I am using:

updateProgress: function (statusurl){
    axios({
      method: 'get',
      url: statusurl,
      dataType: 'json',
      headers: {'Content-Type': 'application/json; charset=utf-8'},
      async: true,
      data: {}
    })
      .then(function (response) {
        var data = response.data
        if (data['state'] !== 'PENDING' && data['state'] !== 'PROGRESS') {
          if ('result' in data) {
            // show result
            console.log('result: ' + data['result'])
          }
          else {
            // something unexpected happened
            console.log('state: ' + data['state'])
          }
        }
        else {
          // rerun in 2 seconds
          setTimeout(function() {
            this.updateProgress(statusurl)
          }, 2000)
        }
      }.bind(this))
      .catch(e => {
        console.log('error: ' + e)
      })

As you can see I am using this.functionA from functionC and bind() on functionA.

I get the following error in the console:

Uncaught TypeError: this.updateProgress is not a function at eval 

Any idea on how to do this?

Upvotes: 1

Views: 72

Answers (1)

skirtle
skirtle

Reputation: 29122

The problem is that the value of this has changed. Every time you enter a new function (as declared with the function keyword) the value of this changes. In this specific case it is the function called by setTimeout that is at fault:

setTimeout(function() {
    this.updateProgress(statusurl)
}, 2000)

In years gone by the solution would be to grab a reference to this under a different name:

var me = this    

setTimeout(function() {
    me.updateProgress(statusurl)
}, 2000)

Slightly less old-school would be using bind, like you have for the other nested function:

setTimeout(function() {
    this.updateProgress(statusurl)
}.bind(this), 2000)

If you have ES6 arrow functions available (and judging by your catch it would seem you have) then you don't even need to use bind. Arrow functions don't change the value of this so you can just write:

setTimeout(() => {
    this.updateProgress(statusurl)
}, 2000)

Your other use of bind can similarly be removed.

Upvotes: 3

Related Questions