Javascript 在同一承诺内将用户和化身URL相互链接

Javascript 在同一承诺内将用户和化身URL相互链接,javascript,reactjs,firebase,promise,Javascript,Reactjs,Firebase,Promise,我需要一些帮助。我从firebase收集所有用户,得到一个包含键值对的对象数组。我想向该对象添加另一个键值对: avatarUrl: 'someurl' 然后我想把它送到我的减速机上 我有点难以将两者结合起来,以下是我取得的成绩: const collectionRef = dbf.collection('users'); const collectionArray = []; collectionRef.get() .then((snapshot) => { s

我需要一些帮助。我从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,
        });
    })
我有一个承诺中的一个承诺,但事情似乎并不顺利

有什么想法吗?

让我们试试看

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)
通过为
addDocIdAndAvatar
使用
async
函数,我们可以
等待
avatarUrl
。类似地,在
collectUsersFromSnapshot
中,我们首先使用
addDocIdAndAvatar
映射快照中的用户集合,这是一个承诺,然后使用
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)

@BennyPowers谢谢,多亏了你的密码,我才解决了这个问题。快照不是数组,用户数组是在创建集合数组后才形成的。因此,我们不得不对其进行一些修改,但最终的结果是:这对asnyc的开发有意义吗

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);
            });
        });

        const getAvatarUrl = userId => storageRef
            .child(`${userId}/avatar.jpg`)
            .getDownloadURL();

        const addDocIdAndAvatar = doc => getAvatarUrl(doc.docId)
            .then(avatarUrl => ({ ...doc, avatarUrl }));

        const dispatchUsers = data => dispatch({ type: actionTypes.DONE, data });
        Promise.all(collectionArray.map(addDocIdAndAvatar))
            .then(dispatchUsers);
    });

感谢您回答benny,我不熟悉async await(应该深入了解一下),不知怎的,我在await snapshot=>dispatch中遇到了一个complile错误({…….在这种情况下,您的构建步骤不支持异步函数,这是一个遗憾。我将制作一个使用流畅流的版本,请稍候。理解异步/await的唯一提示:异步函数返回一个承诺,await关键字是
。然后
如果出现错误,
try/catch
。如果快照不是ar,则catch
ray,你如何得到一个
forEach
实例方法?