首页  >  问答  >  正文

如何在Vue 2中全局函数中返回一个观察者

<p>你好,我有一个问题:在main.js中,我有一个全局函数<code>getSites</code>,用于从API检索站点列表。</p><p> 这个函数使用async/await工作,并异步返回站点数据。</p><p> 我还有一个全局变量叫做<code>lockSitesLoading</code>,当我开始从API获取数据时,我将其设置为true,我需要这个变量来防止客户端向服务器发出新请求。</p><p> 在第一个函数<code>getSites</code>中,我需要检查这个变量<code>lockSitesLoading</code>,如果它为true,就开始监视它直到它变为false。在这一点上,我想递归调用<code>getSites</code>。</p><p> 问题现在开始了,因为当我开始监视变量时,这个函数并不等待变量变为false,而是返回<code>undefined</code>。</p><p> 这里是我的代码:</p> <p>组件.vue:</p> <pre class="brush:php;toolbar:false;">async mounted() { let vm = this; const sites = await vm.getSites(); vm.sites = sites.data },</pre> <p>main.js:</p> <pre class="brush:php;toolbar:false;">async getSites() { let vm = this; if (vm.$store.state.lockSitesLoading) { vm.$watch('$store.state.lockSitesLoading', () => vm.getSites()); } else { return vm._getSitesOnline(); //这是实际从服务器获取数据的函数 }</pre> <p>我尝试以这种方式解决,但不起作用。有什么想法吗?</p>
P粉682987577P粉682987577409 天前466

全部回复(2)我来回复

  • P粉788571316

    P粉7885713162023-09-06 19:21:54

    不清楚你是否设置了lockSitesLoading = true,也不清楚你在哪里设置了。

    这是一个可工作的示例。

    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>

    回复
    0
  • P粉063039990

    P粉0630399902023-09-06 09:50:26

    基本上需要一个等待的承诺:

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

    请注意,如果lockSitesLoading由于某种原因阻止执行,这将导致内存泄漏。

    使用组合API和VueUse组合式可能有更简洁的方法来实现这一点。

    回复
    0
  • 取消回复