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

Data from promise never renders in component

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

Firestore 数据如下所示:

使用 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 创建一个 return 承诺的操作。该操作将首先检查状态中是否有 userProfile。如果有,它只会 return userProfile,如果没有,它会获取它然后 return 它:

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
    })
  }
}

由于此操作现在 return 是一个承诺,您可以在 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;
        })                   
    } 
}