Comment renvoyer un observateur d'une fonction globale dans Vue 2
P粉682987577
P粉682987577 2023-09-05 22:03:02
0
2
503
<p>Bonjour, j'ai une question : Dans main.js, j'ai une fonction globale <code>getSites</code> </p><p> Cette fonction fonctionne en utilisant async/await et renvoie les données du site de manière asynchrone. </p><p> J'ai également une variable globale appelée <code>lockSitesLoading</code> que j'ai définie sur true lorsque je commence à obtenir des données de l'API. J'ai besoin de cette variable pour empêcher le client de faire de nouvelles requêtes au serveur. </p><p> Dans la première fonction <code>getSites</code>, je dois vérifier cette variable <code>lockSitesLoading</code> et si elle est vraie, commencer à la surveiller jusqu'à ce qu'elle devienne false. À ce stade, je souhaite appeler <code>getSites</code> </p><p> Le problème commence maintenant car lorsque je commence à regarder la variable, la fonction n'attend pas que la variable devienne fausse, mais renvoie <code>undefined</code>. </p><p> Voici mon code : </p> <p>Component.vue :</p> <pre class="brush:php;toolbar:false;">monté async() { soit vm = ceci ; const sites = attendre vm.getSites(); vm.sites = sites.données },</pré> <p>main.js :</p> <pre class="brush:php;toolbar:false;">async getSites() { soit vm = ceci ; si (vm.$store.state.lockSitesLoading) { vm.$watch('$store.state.lockSitesLoading', () => vm.getSites()); } autre { return vm._getSitesOnline(); //C'est la fonction qui récupère réellement les données du serveur }</pré> <p>J'ai essayé de résoudre le problème de cette façon, mais cela ne fonctionne pas. Des idées? </p>
P粉682987577
P粉682987577

répondre à tous(2)
P粉788571316

Je ne sais pas si vous l'avez configurélockSitesLoading = true, et je ne sais pas où vous l'avez configuré.

Voici un exemple fonctionnel.

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    sites: [],
    lockSitesLoading: false
  },
  actions: {
    async loadSites(context) {
        context.state.lockSitesLoading = true;    
        const sites = await context.dispatch('getSites');
        context.state.sites = sites.data;
        context.state.lockSitesLoading = false;    
    },
    async getSites(context) {
        return new Promise(function(resolve, reject){
          setTimeout(function(){
            resolve({ data: ['site1', 'site2', 'site3']})              
          },1000)
        })
      }    
  }
})

new Vue(
  { 
    el:'#app',
    store: store,
    async mounted() {
       await this.$store.dispatch('loadSites')
    },
    computed: {
      sites() { return this.$store.state.sites },
      lockSitesLoading() { return this.$store.state.lockSitesLoading }
    },
    watch: {
      lockSitesLoading(newVal, oldVal) {
          console.log(`lockSitesLoading: ${oldVal} -> ${newVal}`)
      }
    }    
  }
)
#app { line-height: 1.75; }
[v-cloak] { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.14/vue.min.js"></script>
<script src="https://unpkg.com/vuex@3.6.2/dist/vuex.js"></script>
<div id="app" v-cloak>
  sites: {{sites}}<br/>
  lockSitesLoading: {{lockSitesLoading}}
</div>
P粉063039990

Nécessite essentiellement une promesse d'attendre :

let unwatch;

  await new Promise(resolve => {
    unwatch = vm.$watch('$store.state.lockSitesLoading', loading => {
      if (!loading) {
        resolve();
      }
    }, { immediate: true });
  });

  unwatch();

  await vm._getSitesOnline();

Veuillez noter que si lockSitesLoadingbloque l'exécution pour une raison quelconque, cela entraînera une fuite de mémoire.

Il existe peut-être un moyen plus propre d'y parvenir en utilisant l'API de composition et les compositions VueUse.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal