javascript - Firestore, onSnapshot() or asyncawait issue or both - Stack Overflow

I'm trying to get an array of changes using Firebase Firestore's onShapshot().I'm havin

I'm trying to get an array of changes using Firebase Firestore's onShapshot().

I'm having trouble retrieving data through onSnapshot(); I may be in trouble with async/await as well, not quite sure...

Can you see where there are problems?

Output should be (but it is currently):

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.

Code:

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.

I'm trying to get an array of changes using Firebase Firestore's onShapshot().

I'm having trouble retrieving data through onSnapshot(); I may be in trouble with async/await as well, not quite sure...

Can you see where there are problems?

Output should be (but it is currently):

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.

Code:

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.
Share Improve this question edited Apr 15, 2023 at 8:37 Renaud Tarnec 83.2k10 gold badges98 silver badges129 bronze badges Recognized by Google Cloud Collective asked Oct 25, 2020 at 8:29 daCodadaCoda 3,8655 gold badges36 silver badges40 bronze badges 2
  • If you only need to retrieve data then don't use onSnapshot() function instead use .get() method then async await will might work. – Zuhair Naqi Commented Oct 25, 2020 at 8:46
  • 1 did you find an answer to this issue? I seem to be having similar issue. – Penguin Commented Jul 5, 2021 at 14:40
Add a ment  | 

2 Answers 2

Reset to default 3

Have a look at this answer which explains the difference between the get() and onSnapshot() methods.

In a nutshell:

  • When you use get() you retrieve all the documents of the collection only once (like a "get and forget").
  • When you use onSnapshot() you constantly listen to the collection.

Note that onSnapshot() is not an asynchronous method, while get() is => don't call onSnapshot() with await.


Since, from your question, it seems that you want to get the list of friends by calling the getAllFriends() method, do as follows:

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

More possibilities are to be found in the Firestore doc, here and here.

I think you just want to track newly added John's friends and add them to the johnFiends array. Perhaps you can just add the onsnapshot listener on top of @Renaud's suggestion:

const getAllFriends = async (userName) => {
    const querySnapshot = await db
      .collection('user')
      .doc(userName)
      .collection('friends')
      .get();
    // You may need check for querySnapshot.empty before proceed
    let allFriends = querySnapshot.docs.map(doc => doc.data());
    return allFriends;
  };

let johnFriends = await getAllFriends('john');
console.log("All John's friends:", johnFriends);

const unsubscribe = db.collection("user").doc("john").collection("friends")
    .onSnapshot(snapshot => {
        snapshot.docChanges().forEach(change => {
            if (change.type === "added") {
                johnFriends.push(change.doc.data());
                console.log("New John's friend:", change.doc.data());
                console.log("New all John's friends:", johnFriends);
            };
        });
    });

Note that onsnapshot is mostly for real-time tracking of data change at the backend and what you should do later in the frontend, therefore you should apply it on real-time handler instead of incorporate it inside a normal data pulling function, e.g. getAllFriends(). In short, handle real-time changes separately.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742418897a4440283.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信