onSnapshot, forEach и get() синхронно на Firebase

#javascript #firebase #google-cloud-firestore

#javascript #firebase #google-облако-firestore

Вопрос:

Я использую firebase .onSnapshot для получения идентификаторов пользователей, находящихся в данный момент в Сети, и сохранения каждого идентификатора в массив. Я успешно развернул .onSnapshot , чтобы получить идентификатор пользователей онлайн, но в конце я возвращаю пустой массив

 var learning_language;
db.collection(ll_profile).doc(user_uid).get().then(function(doc) {
  learning_language = doc.data().learning_language;
})

db.collection(ns_status).where("state", "==", "online").onSnapshot(function(snapshot) {
  var ns_match = [ ];
  snapshot.forEach(function(userSnapshot) {
    db.collection("ns_profile").doc(userSnapshot.id).get().then(function(doc) {
      spoken_language = doc.data().spoken_language;
      if (learning_language == spoken_language) {
        ns_match.push(userSnapshot.id);
        console.log(ns_match);
      }
    })
  })
  return (ns_match);
  

Что я пытаюсь сделать, так это сначала определить, learning_language извлеченный из коллекции ll_profile идентификатор текущего пользователя с именем user_uid.

Затем .onSnapshot прослушивает состояние другой группы пользователей в режиме онлайн (которое автоматически обновляется, если пользователь подключен к сети или оффлайн) внутри ns_status коллекции. После этого возвращенный онлайн-пользователь из .onSnapshot проверяется, совпадает ли spoken_language поле внутри их документа (названное с соответствующим uid) с learning_language определенным ранее. Если он совпадает, то сохраните uid в массиве ns_match.

Значения внутри ns_match верны. Я думаю, .get() выполняется асинхронно. Вот почему ns_match возвращается пустым.

Как я должен вернуть ns_match в конце все значения, сохраненные должным образом?

Заранее спасибо.

Комментарии:

1. Вы можете использовать обещание или обратные вызовы. Нет необходимости делать этот вызов асинхронным

Ответ №1:

 function getMatches() {
  return new Promise(resolve => {
    db.collection(ll_profile).doc(user_uid).get()
      .then(function(doc) {
        var learning_language = doc.data().learning_language;
        db.collection(ns_status)
          .where("state", "==", "online")
          .onSnapshot(function(snapshot) {
            var ns_match = [];
            snapshot.forEach(function(userSnapshot) {
              db.collection("ns_profile")
                .doc(userSnapshot.id)
                .get()
                .then(function(doc) {
                  spoken_language = doc.data().spoken_language;
                  if (learning_language == spoken_language) {
                    ns_match.push(userSnapshot.id);
                    console.log(ns_match);
                  }
                });
            });
            resolve(ns_match);
          });
      });
  });
}


getMatches().then(ns_matches => console.log(ns_matches));

  

Комментарии:

1. Привет, Tanmay, попробовал именно то, что вы предоставили, он по-прежнему возвращает разрешение в виде пустого массива, а затем сохраняет значения внутри после.

Ответ №2:

перенос в обещание — это правильный ход. Однако помните, что snapshot возвращает метаданные о вашем результате. В частности, snapshot.size . Можно использовать это значение для подсчета записей внутри foreach метода или сравнить длину целевого массива со значением snapshot.size