当我尝试从Firestore获取收藏时出现问题

时间:2019-12-24 09:15:17

标签: javascript reactjs firebase google-cloud-firestore

看到所有答案后,我再次编辑了代码。但是我仍然有问题

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

3 个答案:

答案 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,了解相关问题和其他说明,并提供相同问题的其他答案。