Firebase实时数据库读取数据

时间:2020-10-04 14:39:54

标签: javascript reactjs firebase firebase-realtime-database redux

我正在使用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)
                    })
            }
        ))
    }
}

这有效,但我不知道如何仅在数据完全形成后才分派操作,对此有什么解决方案吗?感谢您的帮助!

1 个答案:

答案 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等待所有配置文件加载完毕。
  • 添加了一个地图以在内部回调中查找电子邮件地址。