我正在使用React + Redux和Firebase的实时数据库来构建类似于Messenger的东西。
我习惯从这样的API中检索数据:
export const fetchContacts = () => {
return async dispatch => {
dispatch(fetchContactsStart());
try {
const response = await axios.get('....');
dispatch(fetchContactsSuccess(...));
} catch(e) {
dispatch(fetchContactsFail(...));
}
}
}
现在在Firebase中,我有以下数据: enter image description here
我需要获取所有用户联系人,然后获取与这些联系人相关联的用户信息,并构建如下结构: [{email:...,用户名:...},{email:...,用户名:...},...]。以这种格式获取所有数据后,我想将操作分派给我的减速器。
现在我有以下代码:
export const fetchContacts = () => {
return dispatch => {
dispatch(fetchContactsStart());
const userEmail = firebase.auth().currentUser.email;
let data = [];
firebase.database().ref(`users_contacts/${Base64.encode(userEmail)}`)
.on('value', contacts => contacts.forEach(contact => {
firebase.database().ref(`users/${Base64.encode(contact.val().contact)}`)
.on('value', user => {
data.push({ email: contact.val().contact, username: user.val().username });
console.log(data)
})
}
))
}
}
这有效,但我不知道如何仅在数据完全形成后才分派操作,对此有什么解决方案吗?感谢您的帮助!
答案 0 :(得分:1)
在等待多个异步操作完成时,解决方案通常是使用Promise.all
。在这种情况下,看起来像这样:
export const fetchContacts = () => {
return dispatch => {
dispatch(fetchContactsStart());
const userEmail = firebase.auth().currentUser.email;
let data = [];
firebase.database().ref(`users_contacts/${Base64.encode(userEmail)}`).once('value', contacts => {
let promises = [];
let map = {};
contacts.forEach(contact => {
const contactId = Base64.encode(contact.val().contact);
map[contactId] = contact.val().contact;
promises.push(firebase.database().ref(`users/${contactId}`).once('value'));
});
Promise.all(promises).then((users) => {
users.forEach((user) =>
data.push({ email: map[user.key], username: user.val().username });
})
// TODO: dispatch the result here
}
))
}
}
此处的主要变化:
once()
来加载用户数据,因此仅加载一次并返回承诺。Promise.all
等待所有配置文件加载完毕。