来自 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;
})
}
}
在 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;
})
}
}