0

I need to run one function after another in VueJs

data: function() {
        return {
            stuff: '',
            myArray:[
                {
                    "id": 0,
                    "value1": 0,
                    "value2": '',
                    "etc": ''
                },
            ],
        };
},
methods: {
     fetchData() {
            axios.get('/api/get-data')
                .then(res => {
                    this.myArray = res.data;
                }).catch(err => {
                console.log(err)
            })
        },
     runThisAfterArrayPopulates(){
        /*a bunch of code that relies on the contents from this.myArray , therefore I need this.myArray to be fully populated/finalized, for example*/
       for (i = 0; i < this.myArray.length; i++) {
                /*at this point on development server this.myArray.length is 60, on production it is 1 */
                }
            }
     }
}

I currently execute these functions as follows:

created: function () {
        this.fetchData();
},
mounted: function () {
        document.onreadystatechange = () => {
          if (document.readyState == "complete") {
            console.log('Page completed with image and files to ensure it is executed at the very end')
            this.runThisAfterArrayPopulates();
          }
        }
},

When testing this on my development localhost everything runs as expected.

Once I upload as a production app, the function this.runThisAfterArrayPopulates(); runs when this.myArray only has one object and not the whole axios data, it does not give it enough time to run. I am pretty sure that the reason this is happening is because in the production server my axios takes longer than in my localhost, then I populate the array and since Javascript is async it seems that the function runThisAfterArrayPopulates() runs BEFORE my array is fully populated.

I have read about promises but I am not entirely sure how it would fit here.

I have atempted to run this.fetchData(); inside beforeMounted: instead of created: , I have also tried to call this.runThisAfterArrayPopulates() inside the axios .then() but I am still facing an array of length 1 in production.

Note: I am sure that the code works, its flawless in development, and also if I create a button like this:

<button @click="runThisAfterArrayPopulates()">Click me</button>

The behavior is perfect when I click the button, so I am sure that it has to do with order of execution.

1
  • you could "store" the promise returned by axios.get ... e.g. this.someStoredpromise = axios.get(....etc and use that like this.someStoredPromise.then(this.runThisAfterArrayPopulates) Commented Dec 12, 2020 at 1:29

1 Answer 1

2

Change your code as follows.

    methods: {
         fetchData() {
                
                axios.get('/api/get-data')
                    .then(res => {
                        this.myArray = res.data;
                        this.runThisAfterArrayPopulates(); // Added method call.
                    }).catch(err => {
                    console.log(err)
                })
            },
         runThisAfterArrayPopulates(){
            /*a bunch of code that relies on the contents from this.myArray , therefore I need this.myArray to be fully populated/finalized */
         }
    },


created: function () {
        // this.fetchData();
},
mounted: function () {
        this.fetchData();
},

Since the handler method is an arrow function, this should not cause a problem. If you use a normal function in place of arrow function, take care of this gotcha.

EDIT: you can try moving the this.fetchData(); call to the mounted itself.

Sign up to request clarification or add additional context in comments.

5 Comments

I have tried this as you posted and the behavior is the same, works fine on development but does not work in production. I had to remove "this." from this.runThisAfterArrayPopulates(); for it to work, therefore I ran runThisAfterArrayPopulates(). It still seems that the order of execution has an issue while executing this line: this.myArray = res.data;
@toolnin - makes no sense ... if runThisAfterArrayPopulates is a method: then you really can only run it using this.runThisAfterArrayPopulates
I think created() is getting fired, and this created makes an ajax call to the server. So even before that ajax call returns, the mounted(): is getting called. This order of execution seems to be problem. Remove created(), and just move fetchData to mounted().
my bad, you are absolutely right , "this." is required. I believe your solution worked. Let me test it further and I'll get back to you in a minute. Thanks a lot!
Confirmed, works great in production. This solved the order of execution. Thanks again!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.