Caleb Porzio

Ajax loading wheels and forgotten Promises

Jun 2016

In the beginning...

data: {
  beans: null
},

ready: function() {
  this.$http.get('beans')
    .success(function(response) {
       this.beans = response;
    });
}

<div v-if="beans">
 // write a heaping pile of nested dom
</div>

Then I tried doing things like....

<li v-for="bean in beans">
  <span v-text="bean.soup.is.da.bomb"></span>
</li>

and my console turned bloody red with...

VM19747:1 Uncaught TypeError: Cannot read property 'soup' of null(…)

so I wised up and added...

v-if="bean"

everywhere.

Turns out this makes your html overly verbose and downright muddy, not to mention remembering to add the v-ifs every time you access nested properties.

Again, I wised up...

data: {
  loaded: false,
  beans: {}
},

ready: function() {
  this.$http.get('beans')
    .success(function(response) {
       this.beans = response;
       this.loaded = true;
    });
}

<div v-if="loaded">
 // write a heaping pile of nested dom
</div>

And all was well. Until...

data: {
  loading: true,
  beans: {},
  lentils: {}
},

ready: function() {
  this.$http.get('beans')
    .success(function(response) {
       this.beans = response;
       this.loaded = false;
    });

  this.$http.get('lentils')
    .success(function(response) {
       this.beans = response;
       this.loaded = false;
    });
}
}

<div v-if="!loading">
 // write a heaping pile of nested dom
</div>

I needed to make multiple ajax calls in the same component, and one was slower than the other.

Phew, looking back can be painful. Luckily I've come a long way since then. I now am doing fancy things like writing ES6 and using stores for a lot of the data I need to fetch on page load.

For demonstration purposes I will just show you the technique in a basic component setup. You can utilize this in your root instance, a component, a store, or a mixin - your preference.

data() {
  return {
    ready: false,
    beans: {},
    lentils: {}
  }
},

ready() {
  Promise.all([
    this.loadNetworks(),
    this.loadConnections()
  ]).then(response => {
    this.ready = true;
  });
},

methods: {
  loadBeans() {
    return this.$http.get('beans')
      .then(response => {
         this.beans = response;
         this.loaded = false;
      });
  },

  loadLentils() {
    return this.$http.get('beans')
      .then(response => {
         this.beans = response;
         this.loaded = false;
      });
  }
}

Another thing. If you're not showing the user that something is loading - you are being bad. Stop that right now, roll your sleeves up and keep track of the state of your ajax requests - your users and your javascript will thank you.

- drop the mic.


My Newsletter

I send out an email every so often about cool stuff I'm working on or launching. If you dig, go ahead and sign up!