Firestore 查询,缓慢或返回未定义

Firestore query, slow or returning undefined

我正在尝试检索 2 个查询并在两者之间进行计算。 但它相当慢或返回未定义。

有时它会显示值,但通常是在我刷新应用程序之后。

第一个where,给出字段'active'为真的文档数量。 然后第二部分是检查 active 和 hasread 字段以及 returns 金额。

这是我使用的代码:

export default class Home extends React.Component {
    constructor(props) {
        super(props)
        this.gettingAmount = false;
        this.unsubscribe = null;
        this.announce = firebase.firestore().collection('announcements');
        this.state = {
            newAnnouncements: 0,
        }
    }
    componentDidMount() {
        this.gettingAmount = true;
        let countHasRead;
        let countAnnounce;
        this.unsubscribe = firebase.auth().onAuthStateChanged((user) => {
            if (user) {
                this.announce
                    .where('active', '==', true)
                    .get()
                    .then(snapshot => {
                        countAnnounce = snapshot.size;
                    });
                this.announce
                    .where('active', '==', true)
                    .where('hasread.' + user.uid, '==', true)
                    .get()
                    .then(snapshot => {
                        countHasRead = snapshot.size;
                    })
                    .catch(err => {
                        console.log('Error getting documents', err);
                    });
                setTimeout(() => {
                    console.log('second', countAnnounce, countHasRead);
                    if (this.gettingAmount) {
                        this.gettingAmount = false;
                        this.setState({newAnnouncements: countAnnounce - countHasRead});
                        AsyncStorage.setItem('newAnnouncements', JSON.stringify(countAnnounce - countHasRead));
                    }
                }, 1000);
            }
        });
    }
}

因此 console.log('second') 显示未定义或查询真的很慢并且确实显示了 countAnnounce 和 countHasRead 的值。

是我哪里做错了吗?我不确定为什么它显示为未定义。

请帮忙。

问题不在于查询速度慢,而在于它是异步的。

查看正在发生的事情的一种快速方法是使用一些日志语句:

console.log("Before starting query");
this.announce
    .where('active', '==', true)
    .get()
    .then(snapshot => {
        console.log("Got query results")
    });
console.log("After starting query")

如果您 运行 此代码,它会打印:

Before starting query

After starting query

Got query results

这可能不是您期望的顺序,但这正是应该发生的。由于从 Firestore 加载数据可能需要一些时间,因此该操作在后台进行,而您的其余代码将继续运行。然后当数据加载时,它会用该数据调用你的回调函数,这样你就可以处理它了。

这意味着任何需要从数据库访问数据的代码都必须在回调函数中(从中调用)。

所以在你的情况下,你需要嵌套加载:

if (user) {
    this.announce
        .where('active', '==', true)
        .get()
        .then(snapshot => {
            countAnnounce = snapshot.size;
            this.announce
                .where('active', '==', true)
                .where('hasread.' + user.uid, '==', true)
                .get()
                .then(snapshot => {
                    countHasRead = snapshot.size;
                    console.log('second', countAnnounce, countHasRead);
                    if (this.gettingAmount) {
                        this.gettingAmount = false;
                        this.setState({newAnnouncements: countAnnounce - countHasRead});
                        AsyncStorage.setItem('newAnnouncements', JSON.stringify(countAnnounce - countHasRead));
                    }
                })
                .catch(err => {
                    console.log('Error getting documents', err);
                });
        });

}

与问题无关,我建议阅读 Better Arrays in Cloud Firestore! 因为现在有一种更有效的方法来做到这一点:.where('hasread.' + user.uid, '==', true) 需要更少的索引。