Связывание пользователей и URL аватаров друг с другом в рамках одного и того же обещания - PullRequest
0 голосов
/ 25 сентября 2018

нужна помощь.Из 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,
        });
    })

У меня есть обещание в рамках обещания, и кажется, что дела идут не очень хорошо.

Есть идеи?

Ответы [ 2 ]

0 голосов
/ 25 сентября 2018

@ 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);
    });
0 голосов
/ 25 сентября 2018

Давайте попробуем

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...