首页 > 解决方案 > 在同一个承诺内将用户和头像网址相互链接

问题描述

需要一些帮助。从 firebase 我收集我所有的用户,我得到一个包含键值对的对象数组。对于这个对象,我想添加另一个键值对:

avatarUrl: 'someurl'

然后我想把它分派给我的减速器。

我有点坚持将两者结合起来,这是我走了多远:

const collectionRef = dbf.collection('users');
const collectionArray = [];
collectionRef.get()
    .then((snapshot) => {
        snapshot.forEach((doc) => {
            let withId = {
                docId: doc.id,
                ...doc.data(),
            };
            collectionArray.push(withId);

            storageRef.child(`${doc.id}/avatar.jpg`).getDownloadURL().then((url) => {
                withId = {
                    ...withId,
                    avatarUrl: url,
                };
                collectionArray.push(withId);
            });
        });
        return dispatch({
            type: actionTypes.DONE,
            data: collectionArray,
        });
    })

我有一个承诺中的一个承诺,但事情似乎并不顺利。

有任何想法吗 ?

标签: javascriptreactjsfirebasepromise

解决方案


让我们试一试

const collectionRef = dbf.collection('users');
const storageRef = /*...*/

// getAvatarUrl :: String -> Promise String 
const getAvatarUrl = userId =>
  storageRef
    .child(`${userId}/avatar.jpg`)
    .getDownloadURL()

// addDocIdAndAvatar :: Doc -> Promise {docId, ...docData, avatarUrl}
const addDocIdAndAvatar = async doc => ({
  docId: doc.id,
  ...doc.data(),
  avatarUrl: await getAvatarUrl(doc.id)
});

// collectUsersFromSnapshot :: Snapshot -> Dispatch
const collectUsersFromSnapshot = await snapshot =>
  dispatch({
    type: actionTypes.DONE,
    data: await Promise.all(snapshot.map(addDocIdAndAvatar)),
  });

collectionRef.get()
  .then(collectUsersFromSnapshot)

通过使用async函数 for ,addDocIdAndAvatar我们可以await. avatarUrl类似地,collectUsersFromSnapshot我们首先使用 Promise 映射快照中的用户集合addDocIdAndAvatar,然后使用Promise.allawait整个 Promise 集合解析为一个解析数组,然后将其传递给dispatch

如果您的设置禁止现代 JS 功能(如async函数),您可以使用这个等效的 fluent 版本:

const collectionRef = dbf.collection('users');
const storageRef = /*...*/

// getAvatarUrl :: String -> Promise String 
const getAvatarUrl = userId =>
  storageRef
    .child(`${userId}/avatar.jpg`)
    .getDownloadURL()

// addDocIdAndAvatar :: Doc -> Promise {docId, ...docData, avatarUrl}
const addDocIdAndAvatar = doc => 
  getAvatarUrl(doc.id)
    .then(avatarUrl => ({ docId: doc.id, ...doc.data(), avatarUrl }))

// dispatchUsers :: [User] -> Dispatch
const dispatchUsers = data =>
  dispatch({ type: actionTypes.DONE, data })

// collectUsersFromSnapshot :: Snapshot -> Promise Dispatch
const collectUsersFromSnapshot = snapshot =>
  Promise.all(snapshot.map(addDocIdAndAvatar))
    .then(dispatchUsers)

collectionRef.get()
  .then(collectUsersFromSnapshot)

推荐阅读