Valentine
Valentine

Reputation: 161

How can I display the loading indicator until ajax is completed?

I want to display a loading spinner until my messages finished loading.

I implemented my spinner in my Message.vue:

import backend from '...'

export default {
  mounted: function() {
    this.loadMessages();
  },
  methods: {
    loadMessages() {
      var self = this;
      backend.getMessages().then(function(resp) {
        self.previousDate = null;
        self.messages = resp.data;
        self.openLoader();
      });
    },
    openLoader() {
      let loader = this.$loading.show({
        loader: 'spinner',
        color: '#e32339',
        canCancel: true,
        container: this.$refs.loadingContainer
      });

      setTimeout(() => {
        loader.hide()
      }, 2500)
    },
  }
}

My spinner is displayed over the container for 2500 milliseconds, but I'm just simulating it without knowing when the AJAX request has finished. I quite don´t understand how to display the spinner til the AJAX request is completed. Right now it just displays it for 2500 milliseconds.

My backend.getMessages() method looks like this:

import axios from 'axios'

const host = /* process... */

export default {
  getMessages: function (peer) {
    return axios.get(`${host}/api/messages`, {
      params: {
        me:      localStorage.getItem("user_id"),
        device:  localStorage.getItem("device_id"),
        peer: peer
      }
    }) 
  },
  //...
}

Upvotes: 0

Views: 1694

Answers (2)

politinsa
politinsa

Reputation: 3720

  • Add a var loading in your data.
  • Display <div v-if="loading">Spinner here</div>
  • Then
getMessages: function (peer) {
    this.loading = true; // AJAX request is loading
    return axios.get(`${host}/api/messages`, {
      params: {
        me:      localStorage.getItem("user_id"),
        device:  localStorage.getItem("device_id"),
        peer: peer
      }
    })
  },


loadMessages() {
      var self = this;
      backend.getMessages().then(function(resp) {
        self.previousDate = null;
        self.messages = resp.data;
        self.openLoader();
        self.loading = false // spinner disappear
      });
    },

Upvotes: 1

tony19
tony19

Reputation: 138696

The loader should be shown before the start of your request. Note that axios.get() returns a Promise that resolves when the request is complete, so you could use Promise.prototype.finally off of that Promise to hide the loader:

mounted() {
  // show loader while fetching messages...
  const loader = this.$loading.show()

  backend.getMessages()
    .then(resp => /*...*/)
    .finally(() => loader.hide())
}

Here's another way to write it with async/await:

async mounted() {
  // show loader while fetching messages...
  const loader = this.$loading.show()

  try {
    const resp = await backend.getMessages()
    /*...*/

  } finally {
     loader.hide()
  }
}

Upvotes: 1

Related Questions