Написать асинхронный код в JavaScript Firebase - PullRequest
1 голос
/ 25 марта 2020

Я пытаюсь написать некоторый асинхронный код в JavaScript, особенно я хочу, чтобы код выполнялся после завершения выполнения определенных функций.

Ниже приведен мой код:

 function triggerFunction(duration) {
    var db = firebase.firestore();

    db.collection('users').get().then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
          var data=doc.data();
          db.collection('users').doc(doc.id).collection('#aName').get().then((querySnapshot1) => {
                querySnapshot1.forEach((doc1) => {
                  var firstData = doc1.data()
                  var newID = createRandomId()
                  var alreadyExist = checkAlreadyElementDB(firstData.appType, doc.id)
                  if(firstData.open == true && !alreadyExist){
                      console.log("Entered here: " + alreadyExist)
                      db.collection('#name').doc(newID).set({
                        #NotImportant
                      })
                      db.collection('users').doc(doc.id).collection('#aName').doc(doc1.id).update({
                        open: false
                      })
                  } else if(firstData.open == true && alreadyExist){
                        db.collection('users').doc(doc.id).collection('#aName').doc(doc1.id).update({
                          open: false
                        })
                  }

                })
          })
        });
    });
    setTimeout(triggerFunction, duration);
  }

Я хочу сначала получить результат от функции

var alreadyExist = checkAlreadyElementDB(firstData.appType, doc.id)

Затем продолжить проверку следующей части кода

      if(firstData.open == true && !alreadyExist){
                      console.log("Entered here: " + alreadyExist)
                      db.collection('#name').doc(newID).set({
                        #NotImportant
                      })
                      db.collection('users').doc(doc.id).collection('#aName').doc(doc1.id).update({
                        open: false
                      })
      } else if(firstData.open == true && alreadyExist){
                        db.collection('users').doc(doc.id).collection('#aName').doc(doc1.id).update({
                          open: false
                        })
                  }

Я буду очень признателен помогите с этой проблемой!

Функция checkAlreadyElementDB () выглядит следующим образом:

  function checkAlreadyElementDB(appType, userID){
      var db = firebase.firestore();
      db.collection('#name').get().then((querySnap) => {
        querySnap.forEach((doc) => {
          var opFCData = doc.data();
          if(opFCData.appType == appType && opFCData.userID == userID){
          //  console.log("I HAVE ENTERED HERE")
            return true
          }
        });
      });
      return false
  }

1 Ответ

1 голос
/ 25 марта 2020

Ключ состоит в том, чтобы разбить этот лог c на более мелкие, тестируемые, возвращающие обещания функции. Давайте начнем с checkAlreadyElementDB

// all the functions need this, move it to the top of the file
const db = firebase.firestore();

function checkAlreadyElementDB(appType, userID) {
  return db.collection('#name')
    .where('appType', '==', appType)
    .where('userID', '==', userID).get().then(snapshot => {
      return !snapshot.empty
  })
}

Обратите внимание, как проверка может быть выполнена с помощью предложений where в запросе. Это намного более быстрая операция, передающая клиенту гораздо меньше данных. Обратите также внимание на то, как эта и все другие функции возвращают обещания

Затем центру кода OP потребовалось немного усилий, чтобы распутать. Были вложенные обещания и имена, из-за которых было трудно следовать. Я приложил все усилия, чтобы понять, что имел в виду код, несмотря на то, что не очень понимал приложение.

function closeThenSetOrUpdate(doc) {
  let data = doc.data()
  // update the passed doc, no matter what the checkAlready... result is
  return doc.ref.update({ open: false }).then(() => {
    return checkAlreadyElementDB(data.appType, doc.id)
  }).then(exists => {
    if (data.open && !exists) {
      console.log("Entered here: " + exists)
      const newID = createRandomId()
      return db.collection('#name').doc(newID).set({ #NotImportant })
    } else {
      return Promise.resolve() // just an empty promise
    }
  })
}

Вот функция, которая обрабатывает каждого пользователя, вызывая логи c выше. Обратите внимание, что он собирает обещания и выполняет их все вместе с Promise.all()

function updateANamesForUserWithID(userId) {
  return db.collection('users').doc(userId).collection('#aName').get().then(snapshot => {
    let promises = snapshot.docs.map(doc => {
        return closeThenSetOrUpdate(doc)
    })
    return Promise.all(promises)
  })
}

Теперь, базовую функцию проще написать, используя ту же технику Promise.all() ...

function triggerFunction(duration) {
  return db.collection('users').get().then(snapshot => {
    let promises = snapshot.docs.map(user => {
      return updateANamesForUserWithID(user.id)
    })
    return Promise.all(promises)
  }).then(() => {
    setTimeout(triggerFunction, duration);
  })
}
...