Запрос Firestore, медленный или возвращающий неопределенный - PullRequest
0 голосов
/ 09 января 2019

Я пытаюсь получить 2 запроса и сделать расчет между ними. Но это довольно медленно или возвращает неопределенное значение.

Иногда отображаются значения, но обычно это происходит после обновления приложения.

Первое где, дает количество документов, для которых поле 'active' имеет значение true. Затем вторая часть проверяет поля active и hasread и возвращает сумму.

Это код, который я использую:

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.

Я что-то не так делаю? Я не уверен, почему он отображается как неопределенный.

Пожалуйста, помогите.

1 Ответ

0 голосов
/ 09 января 2019

Проблема не столько в том, что запрос медленный, сколько в том, что он асинхронный.

Быстрый способ увидеть, что происходит, с помощью нескольких операторов журнала:

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

Если вы запустите этот код, он напечатает:

Перед началом запроса

После запуска запроса

Получены результаты запроса

Вероятно, это не тот порядок, который вы ожидали, но это именно то, что должно произойти. Поскольку загрузка данных из 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);
                });
        });

}

Вне зависимости от проблемы, я рекомендую прочитать Лучше Массивы в Cloud Firestore! , потому что теперь есть более эффективный способ сделать это: .where('hasread.' + user.uid, '==', true), который требует гораздо меньше индексов.

...