问题描述
在NativeScript-Vue / Firebase中,我有一个带有诺言的方法,该方法应该从当前用户的关联Firestore文档中获取文档uid的数组。 uid对应于与其他用户(当前用户正在关注的用户又称为“他们的圈子”)关联的文档。
使用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;
})
}
}