Оптимизация обновлений Firestore в реальном времени в приложении чата - PullRequest
0 голосов
/ 02 октября 2018

Я использую обновления Firestore в реальном времени для создания чатов в реальном времени в своем приложении React Native.Я читал, что это, возможно, не лучший способ построить чат, но я решил сделать это, потому что я уже использую Firebase, и чат не является основной целью приложения.Итак, в контексте чата в реальном времени, как бы я оптимизировал соединение Firestore?Обычно это работает очень хорошо, но у меня возникло несколько проблем:

  • сообщение приходит медленно
  • сообщение не отображается после отправки
  • Push-уведомлениеприходит до сообщения

Эти проблемы обычно возникают, когда интернет-соединение не очень хорошее (хотя сообщения Whatsapp по-прежнему работают нормально), но иногда и при хорошем соединении…

Вот как язапросить данные (слушатель в режиме реального времени добавлен в componentDidMount, удален в componenWillUnmount):

onLogUpdate = (querySnapshot) => {
  allMessages = this.state.allMessages

  cb = (allMsgs) => {
    allMsgs.sort((a,b) => {
      a = new Date(a.timestamp);
      b = new Date(b.timestamp);
      return a>b ? -1 : a<b ? 1 : 0;
    })
    messages = _.takeRight(allMsgs, this.state.messageLimit)
    this.setState({ loading: false, messages, allMessages: allMsgs })
  }

  async.map(querySnapshot._changes, (change, done) => {
    if (change.type === "added") {
      const msgData = change._document.data()
        if (msgData.origin == 'user') {
          this.usersRef.doc(msgData.byWhom).get()
            .then(usr => {
              msgData.user = usr.data()
              done(null, msgData)
            })
            .catch(err => { console.log('error getting user in log:', err) })
        } else {
          done(null, msgData)
        }
    } else {
      done(null, 0)
    }
  }, (err, results) => {
    const res = results.filter(el => { return el != 0 })
    allMessages = _.concat(allMessages, res)
    cb(allMessages)
  })
}

И вот как я добавляю новые сообщения:

// in utils.js
exports.addLogMessage = (msgObj, moment_id, callback) => {
  logMessagesRef.add(msgObj)
    .then(ref => {
      momentsRef.doc(moment_id).get()
        .then(doc => {
          const logMsgs = doc.data().logMessages ? doc.data().logMessages : []
          logMsgs.push(ref.id)
          momentsRef.doc(moment_id).update({ logMessages: logMsgs })
        })
        .then(() => {
          if (callback) {
            callback()
          }
        })
    })
    .catch(err => { console.log('error sending logMessage:', err) })
}

// in chat Screen
sendLogMessage = () => {
  if (this.state.newMessage.length > 0) {
    firebase.analytics().logEvent('send_log_message')
    this.setState({ newMessage: '' })
    const msgObj = {
      text: this.state.newMessage,
      origin: 'user',
      timestamp: Date.now(),
      byWhom: this.state.user._id,
      toWhichMoment: this.state.moment._id
    }
    addLogMessage(msgObj, this.state.moment._id)
  }
}

Любые предложениябудет высоко ценится:)

1 Ответ

0 голосов
/ 02 октября 2018

Я работал над чем-то похожим, и после того, как я отправил данные, они не будут отображаться в ListView.Я решил эту проблему, переместив новую запись в существующее ранее сопоставляемое состояние, и, поскольку setState() вызывает метод render(), он работал просто отлично.Я сделал что-то вроде этого:

 sendLogMessage().then(newData => {
     joined = this.state.data.concat(newData);
     this.setState({ data: joined})
 })

Конечно, предполагается, что вы используете this.state.data.map для рендеринга журнала чата.Это будет работать, когда сообщение, которое я отправляю, не может быть просмотрено мной, а что касается сообщений, которые обновляются по мере обновления базы данных, вы можете использовать .onDataChange обратный вызов, предоставляемый Firebase API .Я надеюсь, что помог.

...