Давайте попробуем
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
функцию для addDocIdAndAvatar
, мы можем await
avatarUrl
.Точно так же в collectUsersFromSnapshot
мы сначала сопоставляем коллекцию пользователей в снимке с addDocIdAndAvatar
, обещанием, затем используем Promise.all
до await
разрешение всей коллекции обещаний в массив разрешений, которые мызатем перейдите к dispatch
.
Если ваша установка запрещает современные функции JS, такие как async
функции, вы можете использовать эту эквивалентную версию:
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)