Firestore, onSnapshot () или проблема async / await или и то, и другое

Я пытаюсь получить массив изменений с помощью onShapshot () .

У меня проблемы с получением данных через onSnapshot(); У меня тоже могут быть проблемы с async/await, не совсем уверен ...

Вы видите, где есть проблемы?

Вывод должен быть (но он есть на данный момент):

1. New friends: ... // via onSnapshot(). Should not be empty, but it is (However, it does get populated afterwards).
2. All friends: ... // Should not be empty, but it is.
3. Fred's friends: ... // Should not be empty, but it is.

Код:

const getAllFriends = async () => {
    // Gets all friends by connecting to Firestore's onSnapshot stream.

    const getNewFriends = async () => {
        // Sets up a onSnapshot() stream, and returns a newFriends array with their names.
        // Problem: It initially return an empty array, when it shouldn't be empty.

        let newFriends = [];
        await db.collection("user").doc("john").collection("friends").onSnapshot(snapshot => {
            snapshot.docChanges().forEach(change => {
                newFriends.push({ friend: "Emily" });
            });
        });

        console.log("1. New friends: ", newFriends, newFriends.length); // Length should not be 0.
        return newFriends;
    }

    // John starts with no friends:
    let friends = []; 

    // John should now have found some friends:
    let friendChanges = await getNewFriends(); 
    friends = friends.concat(friendChanges);

    console.log("2. All friends:", friends); // Should contain a few Emilys.
    return friends;
};

let johnFriends = await getAllFriends();
console.log("3. John's friends:", friends); // Should contain a few Emilys.

person daCoda    schedule 25.10.2020    source источник
comment
Если вам нужно только получить данные, не используйте функцию onSnapshot (), вместо этого используйте метод .get (), тогда async await может работать.   -  person Zuhair Naqi    schedule 25.10.2020
comment
вы нашли ответ на этот вопрос? Кажется, у меня похожая проблема.   -  person Penguin    schedule 05.07.2021


Ответы (1)


Взгляните на этот ответ, в котором объясняется разница между методами get() и onSnapshot().

В двух словах:

  • Когда вы используете get(), вы извлекаете все документы коллекции только один раз (например, "получить и забыть").
  • Когда вы используете onSnapshot(), вы постоянно слушаете сборник.

Обратите внимание, что onSnapshot() не является асинхронным методом, а get() is = ›не звоните onSnapshot() с await.


Поскольку из вашего вопроса кажется, что вы хотите получить список друзей, вызвав метод getAllFriends(), сделайте следующее:

  const getAllFriends = async (userName) => {
    const querySnapshot = await db
      .collection('user')
      .doc(userName)
      .collection('friends')
      .get();
    return querySnapshot;
  };

  let johnFriends = await getAllFriends('john');
  johnFriends.forEach(doc => {
    console.log(doc.id, ' => ', doc.data());
  });

Дополнительные возможности можно найти в документе Firestore, здесь и здесь.

person Renaud Tarnec    schedule 25.10.2020
comment
Спасибо @Renaud, я мог бы использовать get (), но он получит данные только один раз (?); Я хочу настроить слушателя (поэтому хочу использовать onSnapshot ()). Думаю, придется перебирать friendChanges по-другому ... - person daCoda; 26.10.2020
comment
Не могли бы вы объяснить, какова ваша точная цель? Вы можете очень хорошо настроить слушателя на collection("user").doc("john").collection("friends")collection. Но учтите, что если вам нужно слушать collection("user").doc("Emily").collection("friends"), вам нужно установить другого слушателя. Если вам нужно прослушать ВСЕ документы друзей, вы должны прослушать запрос группы сбора, например db.collectionGroup('friends'). Скажите, соответствует ли это вашим потребностям, и я обновлю ответ. - person Renaud Tarnec; 26.10.2020
comment
Вот что должно произойти: когда Джон входит в систему, Джон получает список друзей в формате HTML, использующий данные из db.collection("user").doc("john").collection("friends"). Когда Джон добавляет нового друга, его коллекция друзей в Firestore обновляется, как и его список друзей в формате HTML (вот почему я думаю, что onSnapshot() может быть подходящим вариантом. Я полагаю, что сначала я могу получить get(), когда он войдет в систему, а также иметь onSnapshot() для прослушивания последующих изменений; любопытно узнать, что вы думаете, спасибо!). - person daCoda; 27.10.2020