toolnin
toolnin

Reputation: 144

Javascript / Vue Executing a function after another (synchronously)

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.

Upvotes: 0

Views: 2878

Answers (1)

dotcoder
dotcoder

Reputation: 2921

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.

Upvotes: 2

Related Questions