4

I made a "OffersPlugin" that during "install" function get some data from server. And that data is needed in first component loaded in vue. But http request can't finish before vue component is loaded and I don't have any data to use.

How can I tell vue to hold init vue before plugin is ready?

Thank you.


import Vue from 'vue';

import VueCookie from 'vue-cookie';
import App from './ExampleComponent';

import OffersPlugin from '../plugins/OffersPlugin';


Vue.use(VueCookie);
Vue.use(OffersPlugin);

if(document.getElementById("vue-promotion-edit-section")) {
    new Vue({

        render: h => h(App)
    }).$mount('#vue-promotion-edit-section');

In install method I have axios GET request. In that request I load from server list of offers. When request is success then I make plugin variable associated array:

const offerList = [];

As a prototype I use method getOfferId.

function(name) 
{
return offersList[name] || 'No offer'
}

Klick
  • 1,418
  • 1
  • 23
  • 45
  • 1
    Would you like to show how the OffersPlugin code looks like? – Jefry Dewangga Nov 12 '19 at 04:56
  • I can't show exactly it right now (I'm on other pc). I edited my question added plugin concept. – Klick Nov 12 '19 at 06:07
  • 1
    Why don't use conditional statement `v-if` to check if array is empty or not to render what you need? – Daniyal Lukmanov Nov 12 '19 at 06:12
  • My base question: is it possible to mount "vue" when plugin finish http request and data in plugin is ready? I could use v-if or something else like use store. But in this case I need functionality that I described. – Klick Nov 12 '19 at 06:50

2 Answers2

7

HTTP request is asynchronous by nature. Vue initialisation is synchronous by nature. You cannot make a synchronous result out of an asynchronous operation in Javascript.

Workaround :

OffersPluginFactory.js:

const pluginFactory = function() {
  let promise = axios.get()
    .then(...process data...)
    // return plugin object with data inside
    .then(data => ({
      install(Vue, options) {
        ...use data here...
      }
    }));
  return promise; // when resolved this promise returns plugin object
}

export default pluginFactory;

main.vue:

import OffersPluginFactory from '../plugins/OffersPluginFactory';

OffersPluginFactory().then( function(plugin) {
  Vue.use(plugin)

  new Vue({
    render: h => h(App)
  }).$mount('#vue-promotion-edit-section');
} 
);
Michal Levý
  • 33,064
  • 4
  • 68
  • 86
  • Won't that block the rendering till the data is resolved? – Random Jun 30 '20 at 02:46
  • 1
    @Random Yes, that was the point of the original question - "How can I tell vue to hold init vue before plugin is ready". In most real life cases it is better to write your app/components so it works without any data (renders some stub or shows progress) and execute data fetching from lifecycle hooks (created/mounted)... – Michal Levý Jun 30 '20 at 08:27
  • Makes sense, was looking for a non-blocking pattern for async plugins when came across this question – Random Jun 30 '20 at 09:16
-1

try to use beforeCreate(){} inside Vue.

https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

tony19
  • 125,647
  • 18
  • 229
  • 307
Alfarouq
  • 173
  • 1
  • 6