Это потому, что часть кода console.log
выполняется синхронно до того, как какие-либо данные будут фактически записаны в массив. forEach
свойство массива создает неблокирующий обратный вызов независимо от основного исполнения. Если вы хотите убедиться, что каждый элемент в snap
обработан перед выполнением console.log
, я рекомендую вместо этого использовать map
, у карты есть уникальное свойство - фактически возвращать значение (в отличие от foreach). В этом случае это возвращаемое значение будет обещанием обратного вызова. Вы можете просто дождаться результата карты, чтобы убедиться, что все элементы были записаны в массив, или даже лучше вернуть фактические элементы внутри обратного вызова.
вот пример кода (для простоты я удалил usersArray.push({test: 'test'})
который, я полагаю, не нужен)
useEffect(() => {
return db.collection('users').orderBy('lastName').onSnapshot(snap => {
const usersArrayPromise = snap.documents.map(doc => {
const user = doc.data();
if (user.manager) return Promise.all([
db.collection('users').doc(user.manager).get(),
db.collection('roles').doc(user.profile).get()
]).then(resp => {
const manager = resp[0].data();
const role = resp[1].data();
return {id: doc.id, ...user, manager: `${manager.lastName} ${manager.name} ${manager.middleName}`, role: role.profile};
});
return db.collection('roles')
.doc(user.profile)
.get().then(resp => {
const role = resp.data();
return {id: doc.id, ...user, role: role.profile}
})
});
Promise.all(usersArrayPromise).then(usersArray => {
console.log(usersArray)
setAgents(usersArray)
});
})
}, []);
Пожалуйста, обратите внимание на тот факт, что firebase QuerySnapshot не является реальным массивом, но реализует массив, такой как forEach
свойство, если вы хотите использовать map, вы должны сделать snap.documents.map
.