来自诺言的数据永远不会在组件中呈现

问题描述

在NativeScript-Vue / Firebase中,我有一个带有诺言的方法,该方法应该从当前用户的关联Firestore文档中获取文档uid的数组。 uid对应于与其他用户(当前用户正在关注的用户又称为“他们的圈子”)关联的文档。

Firestore数据如下所示:

Firestore data

使用vue-devtools,它在页面数据中显示circleList由正确的数据数组填充。问题是,它永远不会在Listview中呈现,并且isLoading永远不会更改为false。我的假设是,组件在加载数据之前尝试呈现。我曾尝试使用async / await来解决该问题,但这使Vuex的userProfile信息也无法呈现。

代码如下:

<template>
   <Page>
        <StackLayout>
            <Label text="Loading" v-if="isLoading"/>
            <Listview for="item in circleList" v-else>
                    <Label :text="item.name"/>
            </Listview>
        </StackLayout>
   </Page>
</template>


<script>
   import { mapState } from "vuex";
   const firebase = require("nativescript-plugin-firebase/app");
   const userDataCollection = firebase.firestore().collection("userDataCollection");

 export default {
    data() {
        return {
            isLoading: true,circleList: [],item: {}
        }
    },created() {
         this.getCircle();
    },computed: {
        ...mapState(['userProfile'])
    },methods: {
        getCircle() {
            var circle = this.userProfile.circle
            const promises = circle.map(u => userDataCollection.doc(u).get())

            return Promise.all(promises).then(results => {
                results.map(docSnapshot => {
                    this.circleList.push(docSnapshot.data())
                    this.isLoading = false
                })
            })
                                    
        } 
    }
};

解决方法

由于userProfile也是异步的,因此您必须等待它解析后才能在getCircle中创建第一个映射。

我喜欢这样做的方法是为userProfile创建一个返回承诺的动作。该操作将首先检查状态中是否存在userProfile。如果存在,它将仅返回userProfile,否则,将获取它,然后将其返回:

const actions = {
  getUserProfile({state}) {
    return new Promise((resolve,reject) => {
      if (state.userProfile) {
        resolve(state.userProfile);
        
        return;
      }

      // UserProfile is not yet fetched,so fetch it,add it to state.userProfile
      // and resolve the response so you can use it in Vue
    })
  }
}

由于此操作现在返回了承诺,因此您可以在Vue中等待它:?

created() {
   this.getCircle();
},methods: {
    ...mapActions(['getUserProfile']),async getCircle() {
        let circle = [];

        try {
          const userProfile = await this.userProfile();
          circle = userProfile.circle;
        } catch (error) {
          // Some error handling here
        }
        
        const promises = circle.map(u => userDataCollection.doc(u).get())

        Promise.all(promises).then(results => {
            this.circleList = results.map(docSnapshot => docSnapshot.data())
            this.isLoading = false;
        })                   
    } 
}