看到所有答案后,我再次编辑了代码。但是我仍然有问题
const getPosts = async () => {
const snapshot = await firestore.collection('posts').get();
const posts = snapshot.docs.map((doc) => ({ ...doc.data() }));
return posts; };
const PostsList = () => {
let postsData = null;
getPosts().then((posts) => {
postsData = posts;
});
console.log(postsData); // null
return postsData.map((post) => <PostItem key={post.id} event={post} />); };
答案 0 :(得分:2)
get()
返回一个Promise
,用于异步代码。
then()
方法返回一个Promise。它最多包含两个参数:Promise成功和失败案例的回调函数。
因此,console.log(posts);
方法之外的then
将返回未定义状态,因为尚未检索数据。您需要执行以下操作:
const getPosts = () => {
const posts = [];
firestore.collection(`posts`).get().then((snapShot) => {
snapShot.docs.forEach((doc) => {
let data = { ...doc.data() };
posts.unshift(data);
console.log(posts);
console.log(posts[1]);
});
});
};
如果要在then()
方法之外访问数组,则可以返回Promise
:
const getPosts = () => {
const posts = [];
return new Promise((resolve, reject) => {
firestore.collection(`posts`).get().then((snapShot) => {
snapShot.docs.forEach((doc) => {
let data = { ...doc.data() };
posts.unshift(data);
console.log(posts);
resolve(posts);
console.log(posts[1]);
});
});
});
};
然后您可以执行以下操作:
getPosts().then((posts) => {
console.log(posts);
});
检查以下链接:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
答案 1 :(得分:2)
您在此处介绍了异步代码。
firestore.collection(`posts`).get().then((snapShot) => {
snapShot.docs.forEach((doc) => {
let data = { ...doc.data() };
posts.unshift(data);
});
});
get()方法返回一个promise,一旦解析,它将在.then()方法内部处理。这意味着,只有then()内部的内容将等待其执行完成,并且该块外部的任何内容都将被同步执行。
在您的情况下,所有console.log()方法都将在从Fire基础实际获取数据之前执行。要修复它,您可以像Peter所说的那样在then()方法中处理数据,也可以使用async/await。
示例:
var promise1 = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('foo');
}, 300);
});
const consoleIt = async () => { // returns a promise implicitly
value = await promise1;
console.log('value',value)
}
consoleIt(); // Expected output: "value" "foo"
//or
const consoleIt2 = async () => { // returns a promise implicitly
value = await promise1;
return value;
}
consoleIt2().then(value => console.log('value', value)); // Expected output: "value" "foo"
您的代码应为:
const getPosts = async () => {
const posts = [];
let snapShot = await firestore.collection(`posts`).get(); // rest of the code will wait for the snapShot value.
snapShot.docs.forEach((doc) => {
let data = { ...doc.data() };
posts.unshift(data);
});
console.log(posts);
console.log(posts.length);
console.log(posts[1]); // Will print the object.
return posts;
};
异步函数通常返回诺言。您可以像这样调用该功能
const posts = await getPosts();
要么
getPosts().then((posts)=> {console.log(posts)})
您的代码应该是这样
const PostsList = () => {
getPosts().then((posts) => {
console.log(posts); // prints object
return posts.map((post) => <PostItem key={post.id} event={post} />); };
});
// or if you want to handle no data.
let posts = null;
const PostsList = () => {
getPosts().then((res) => {
post = res;
console.log(posts); // prints object
});
return posts? posts.map((post) => <PostItem key={post.id} event={post} />) : <NoData/>;
}
注意:await关键字只能在异步函数内使用!
答案 2 :(得分:2)
我通常建议避免使用push对数组进行变异。也就是说,您可以从函数中返回帖子,以便更轻松地处理它们。
const getPosts = async () => {
const snapshot = await firestore.collection('posts').get();
return snapshot.docs.map(snap => Object.assign({}, { ...snap.data() }))
}
await关键字将延迟依赖于“快照”的代码的执行,直到Promise被解决为止。
编辑 我再次将其以原始形式放置,因为它简洁易读。问题在于,也应该等待getPost函数,因为如果您执行以下操作:
const posts = getPosts()
它将立即使用,而不必等待getPost()完成。您可以在.getPosts中使用.then,例如:
getPosts().then(result => console.log(result))
您还可以将使用getPosts()的函数包装在async / await中,并可以使用其结果,因为它是同步函数。
请参考here,了解相关问题和其他说明,并提供相同问题的其他答案。