Stephan-v
Stephan-v

Reputation: 20289

How to wait for ajax call from main Vue instance?

I currently have VueJS components that makes an ajax call to github like so:

(Child) component

Vue.http.get('user/repos').then((response) => {
    console.log(response);
}, (response) => {
    console.log(response);
});

The problem is that I first need to get an access token before I can make this ajax call. This access token is stored in the database so my main Vue component is making the ajax call to set a common header to all ajax calls:

Main Vue instance

Vue.http.headers.common['Authorization'] = `token ${this.token}`;

const app = new Vue({
    el: '#app',

    data: {
      token: ''
    },

    created() {
        Vue.http.get('/token').then((response) => {
            this.token = response.data.token;
        }, () => {
            console.log('failed to retrieve the access token for the logged in user.');
        })
    }
});

How can I be sure that before running the ajax call from my component that the ajax call to set the 'Authorization' header has been successful?

Upvotes: 3

Views: 4792

Answers (2)

Amresh Venugopal
Amresh Venugopal

Reputation: 9549

Adding this for anyone else who could benefit.

  1. Get the token from the API call, add it up in a vuex state variable.

  2. Access the same using a getter in the child component, as a computed property or you can pass it on as props or via an event bus but both the ways are not as powerful as using vuex.

  3. watch over the property, and perform your required action when the token is obtained.

    // Add this up in the child component
    
       computed: {
         ...mapGetters({
            token: <name-of-the-getter> // token becomes the alias for the computed
         })                            // property.
       },
    
       watch: {
         token () {
           if(this.token) this.someAPICall()// or some other applicable condition
         }
       },
    
       methods: {
         ...mapActions({
           someAPICall: <name-of-the-action>
         })
       }
    
    // ----------------------------------------------
    

Watch requires the value to change, I have noticed that commits made in an action cause the watch to trigger. So if for some reason the token is lost, or expires you will naturally not be able to make the subsequent requests.

EDIT

import store from 'path/to/store'

axios.interceptors.response.use(function (response) {
  // extract the token from the response object
  // save the token to the store for access during subsequent
  // requests.
  return response;
}, function (error) {
  // Do something with response error
  return Promise.reject(error);
});

axios.interceptors.request.use(function (config) {
  // use store getters to access token
  return config;
}, function (error) {
  // Do something with request error
  return Promise.reject(error);
});

Upvotes: 5

c-smile
c-smile

Reputation: 27450

You can replace/proxyfiy Vue.http.get function by your own function that will request token first and then do your request, rough idea:

!function() 
{ 
  var vue_http_get = Vue.http.get;
  var token = null;

  // patching/proxying Vue.http.get function   
  Vue.http.get = function get() {
    vue_http_get.apply(Vue.http,"path/to/get/token/").then(function(resp){
      token = resp; 
      Vue.http.headers.common['Authorization'] = ...;
      // putting back original Vue.http
      Vue.http = vue_http_get;
      return Vue.http.get(arguments[0]);
    });
  }; 
}();

Upvotes: 1

Related Questions