Vue 2.X - Good approach towards waiting for contrasting async data sources in a component

Viewed 134

Within a Vue component I have two async calls for data from different sources (one a HTTP call, one a browser cache call) and I want to have a loader spin until both are complete. When both are complete the component is loaded so to speak.

...
data() {
    return {
      loading: true
    }
},
mounted: function() {
    this.getData(); // HTTP Async API
    this.getOtherData(); // IndexedDB Async API 
},
...

I'm trying to figure out the proper way to set loading to false when both return data. My current approach of using flags looks dirty but I'm not sure if its the best approach.

...
data() {
    return {
      loading: true,
      flagA: false,
      flagB: false
    }
},
mounted: function() {
    this.getData(); // HTTP Async API
    this.getOtherData(); // IndexedDB Async API 

},
methods: {
  getData() {
   ...
   //Once done
   this.flagA = true
   if (this.flagA == true && this.flagB == true) this.loading = false
  },
  getOtherData() {
   ...
   //Once done
   this.flagB = true
   if (this.flagA == true && this.flagB == true) this.loading = false
  }
...

Is there a better approach?

EDIT to show non HTTP function:

getOtherData() {
    var request = indexedDB.open("Database", 1);
    request.onerror = event => {
        //IndexedDB is not supported. Resort to fallback option and continue regular program flow
    };
    request.onsuccess = event => {
      this.db = event.target.result;

      var transaction = this.db.transaction(["project"], "readwrite");

      var projectStore = transaction.objectStore("project");
      var projectReq = projectStore.get(1);

      projectReq.onsuccess = () => {
        this.flagB = true;
      };
      projectReq.onerror = () => {
        //error 
      };
  };
1 Answers

As long as both functions return a promise, use an async lifecycle hook and Promise.all. It works regardless of whether that promise comes from an http request or is just returned from a method:

async mounted() {
  const p1 = axios.get('getData');      // not awaited, just returning promise
  const p2 = this.getOtherData();       // not awaited, just returning promise

  // awaiting both, responses will be in `response1` and `response2`
  const [ response1, response2 ] = await Promise.all([p1, p2]);    
  this.loading = false;
}

Make sure that all functions return a promise if you don't use the http promise directly:

getData() {
  ...
  return request;
},
getOtherData() {
   ...
   return request;
}
Related