Search code examples
vuejs2cdn

Vue js, async inside foreach loop


created () {
    this.test();
},

test : function () {
        axios.get('/api/1', {
            headers : {
                'Access-Control-Allow-Origin' : '*',
                'session' : window.session_id
            }
        }).then((response) => {

            for (const item of response.data) {
                axios.get('/api/2', {
                    headers : {
                        'Access-Control-Allow-Origin' : '*',
                        'session' : window.session_id
                    }
                }).then((response) => {
                    item.subscribers = response.data.filter(o => { return o.status > 0 }).length;
                });
            };

            this.list = response.data;

        }).catch((error) => {
            console.log(error)
        })
    },

<tr v-for="val in list">
    @{{ val.subscribers }}
</tr>

here i am not getting 'subscribers' in the template as it is loading after rendering or i m not sure. how can i use async/await to load all data then render to the view

TIA


Solution

  • The problem is here

                for (const item of response.data) {
                    axios.get('/api/2', {
                        headers : {
                            'Access-Control-Allow-Origin' : '*',
                            'session' : window.session_id
                        }
                    }).then((response) => {
                       // This finishes later than
                       // this.list = response.data occurs
                        item.subscribers = response.data.filter(o => { return o.status > 0 }).length;
                    });
                };
    
                this.list = response.data;
    

    You assign this.list which triggers Vue to re-render. Only later you assign subscribers to each individual item which Vue cannot detect. There are plenty of ways how to properly wait for the response. Because you are basically need everything to resolve in a synchronous way, I'd suggest to use async/await syntax for readability. I haven't tested the code, there might be a typo. But it gives you an idea I hope.

    
    async function test() {
      try {
        const response = await axios.get('/api/1', {
          headers: {
            'Access-Control-Allow-Origin': '*',
            session: window.session_id,
          },
        });
    
        await Promise.all(response.data.map(async (item) => {
          const subscribers = await axios.get('/api/2', {
            headers: {
              'Access-Control-Allow-Origin': '*',
              session: window.session_id,
            },
          });
          item.subscribers = subscribers.filter((o) => o.status > 0).length;
        }));
    
        this.list = response.data;
      } catch (error) {
        console.log(error);
      }
    }