Как я могу непрерывно возвращать в реальном времени результаты обновления Firebase docChanges из функции? - PullRequest
0 голосов
/ 20 июня 2019

Я чувствую, что упускаю что-то простое, но я просмотрел документацию Firebase и просмотрел все соответствующие сообщения SO, которые смог найти.

У меня есть следующая функция:

const checkUsername = username => {
  const fb = require('../firebaseConfig.js')

  fb.usernamesCollection.onSnapshot(querySnapshot => {
    let isValid = querySnapshot.docChanges().every(change => {
      return !(
        (change.type === 'added' && change.doc.id === username) ||
        (change.type === 'removed' && change.doc.id !== username)
      )
    })
    console.log('result 1: ', isValid)
    callback(isValid)
  })
}

Я передаю результат checkusername в пользовательское правило VeeValidate, поэтому оно должно быть логическим значением

С этой целью я пытаюсь вернуть значение isValid, котороеустанавливается на основе (в данном случае) наличия или отсутствия имени пользователя в моем usernamesCollection и оценивается каждый раз, когда новый документ добавляется / удаляется из коллекции.

Поскольку любое изменение в коллекции в Firebase вызоветisValid Чтобы быть пересчитанным, я не могу полагаться на завершение всего этого в Обещании и возвращать его, поскольку оно будет выполняться только при изменении ввода из-за его работы в сочетании с VeeValidate.

Полнаякод можно увидеть ниже:

import { Validator } from 'vee-validate'

const checkUsername = username => {
  const fb = require('../firebaseConfig.js')

  fb.usernamesCollection.onSnapshot(querySnapshot => {
    let isValid = querySnapshot.docChanges().every(change => {
      return !(
        (change.type === 'added' && change.doc.id === username) ||
        (change.type === 'removed' && change.doc.id !== username)
      )
    })
    console.log('result 1: ', isValid)
    callback(isValid)
  })
}

const uniqueUsername = value => {
    const Filter = require('bad-words')
    const filter = new Filter()
    const username = value.toLowerCase().trim()

    let isValid = false

    try {
        if (!filter.isProfane(username)) {
            checkUsername(username, available => {
                console.log('result 2: ', available) //<---Not available outside this scope
            })
        }
        return {
            valid: isValid
        }
    } catch (err) {
        console.log(err)
        return {
            valid: false
        }
    }
}

Validator.extend(
    'unique_username',
    {
        getMessage: field => `${field} is not available.`,
        validate: uniqueUsername
    },
    {
        immediate: false
    }
)

Скорее всего, это проблема асинхронного вызова Firebase, но я не уверен, как изменить свой код в соответствиине для этого.Любая помощь приветствуется, спасибо!

1 Ответ

0 голосов
/ 20 июня 2019

Хорошо, так что если вы заставите checkUsername вернуть обещание, которое разрешается с помощью isValid, то вы можете ожидать этого в uniqueUsername

const checkUsername = username => {
  return new Promise(resolve => {
    const fb = require('../firebaseConfig.js')

    fb.usernamesCollection.onSnapshot(querySnapshot => {
      let isValid = querySnapshot.docChanges().every(change => {
        return !(
          (change.type === 'added' && change.doc.id === username) ||
          (change.type === 'removed' && change.doc.id !== username)
        )
      })
      console.log('result: ', isValid)
      resolve(isValid);
    });
  });

}

const uniqueUsername = async value => {
  const Filter = require('bad-words')
  const filter = new Filter()

  const username = value.toLowerCase().trim()
  let isValid = false

  try {
    if (!filter.isProfane(username)) {
      const isValid = await checkUsername(username) // <--- this is where I want the value returned to
    }
    return {
      valid: isValid
    }
  } catch (err) {
    console.log(err)
    return {
      valid: false
    }
  }
}
...