0

I have the following vue.js code using django as a backend.

The response is coming through fine, but I can't seem to set the variable properly.

Am I doing something wrong with the assignment?

Thanks

<script>
import axios from 'axios'

//Datatable
export default {
    data () {
        return {
            items: [],
        }
   mounted () {
        this.getItems()
    },
methods: {
        getItems() {
            const newLocal='http://127.0.0.1:8000/items/'
            axios({
                method: 'get',
                url: newLocal,
                auth: {
                    username: 'login',
                    password: 'pass'
                }
            }).then(response => {
                    let result = [];
                    result = response.data; 
                    console.log(response.data); 
                    console.log("Data length: " + response.data.length);   /// Returns '7'
                    console.log("Result length: " + result.length);        /// Returns '7'
                    this.items = result;
                    console.log("Item length #1: " + this.items.length)    /// Returns '7'
                })   

            console.log("Item length #2: " + this.items.length)            /// **Returns '0' ???**
        },
Jordan
  • 9,014
  • 8
  • 37
  • 47

2 Answers2

2

The last line returns 0 because the above Axios call is an asynchronous function. The line console.log("Item length #2: " + this.items.length) is executed before the call.

To solve this issue you can use ES6 async... await.

methods: {
        async getItems() {
            const newLocal='http://127.0.0.1:8000/items/'
            await axios({
                method: 'get',
                url: newLocal,
                auth: {
                    username: 'login',
                    password: 'pass'
                }
            }).then(response => {
                    let result = [];
                    result = response.data; 
                    console.log(response.data); 
                    console.log("Data length: " + response.data.length);   /// Returns '7'
                    console.log("Result length: " + result.length);        /// Returns '7'
                    this.items = result;
                    console.log("Item length #1: " + this.items.length)    /// Returns '7'
                })   

            console.log("Item length #2: " + this.items.length)            /// **Returns '0' ???**
        },
  • Is this the recommended approach for loading data on page load? – Jordan Sep 07 '20 at 15:12
  • Basically async...await is the way of making asynchronous method synchronous. In this case, before moving to the next line it will finish executing the Axios call. If you want to use the result right after the execution of the request this is the best approach. – user13284932 Sep 08 '20 at 17:09
1

Axios does an async call so when you are actually logging,

console.log("Item length #2: " + this.items.length)  /// **Returns '0' ???**

that is happening before the response is returned. Since JS is a single threaded language, all the async calls that are executed are put back on to the stack by reading from a separat queue by the event loop. This happens whenever you stack is completely empty and only then will the event loop actually put the async callbacks on the stack again. If you want to check this, put a loop just after the axios call for 1M times and then see, you will see even though your response must have returned by now, the then callback is not triggered unless the loop exits.

For more clarity, refer to https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

In case you want to do something after the axios call returns a response, use promise or async/await.

Let me know if you want to know more about the event loop and how any JS engine works at its core.

Dhwanil shah
  • 458
  • 3
  • 12