Firestore onSnapshot()方法触发多次 [英] Firestore onSnapshot() method fires multiple times

查看:41
本文介绍了Firestore onSnapshot()方法触发多次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有多个路由和vuex的vue-cli-4应用程序.Firestore数据库已成功连接-我的应用程序立即反映了从Firestore控制台应用于数据库的修改.

I have a vue-cli-4 app with multiple routes and vuex. Firestore database has been connected successfully - my app immediately reflects modifications applied to DB from Firestore console.

在离开包含与Firestore同步"了组件的路由并返回之后,开始出现奇怪的行为.在这种情况下,在Firestore控制台中修改数据后, onSnapshot()方法将多次触发.

Strange behavior begins to happen after leaving the route which contains component "synced" with Firestore and then returning back. In this case onSnapshot() method fires multiple times after modifying data in Firestore console.

我想知道我是否应该在离开路线后每次以某种方式手动"从Firestore退订-也许是在 destroyed()钩子上.

I wonder whether I should somehow "manually" unsubscribe my component from Firestore each time after leaving the route - maybe on destroyed() hook.

代码部分:通过在 created()上触发 getDataPie 操作,我正在将 PieChart.vue 组件(位于/pie路线上)与Firestore同步.strong>钩子.

Code part: I'm syncing PieChart.vue component (located on /pie route) with Firestore by firing getDataPie action on created() hook.

<script>
import { mapActions, mapGetters } from 'vuex'

export default {
  name: 'PieChart',

 created () {
   this.getDataPie()
 },

 methods: {
   ...mapActions([
       ...
       'getDataPie',
       ...
    ])
  }
}
</script>

<template>
  ...
</template>

在vuex模块中:

import { getDataPie } from '../../helpers/helpersPie.js'

...

actions: {
  ...
  getDataPie: async ({ commit, getters }) => {
    await getDataPie()
  },
  ...
}

getDataPie 函数,其中包含 console.log ,该函数可让我查看多少次 onSnapshot()已执行:

getDataPie function, containing console.log which allows me to see how many times onSnapshot() has been executed:

export function getDataPie () {
  // get data from firestore, onSnapshot - changes listener
  let fdata = []
  return db.collection('expenses').onSnapshot(res => {
    console.log('-------on snapshot--------------')
    res.docChanges().forEach(change => {
    const doc = { ...change.doc.data(), id: change.doc.id }

    // forming data array
    switch (change.type) {
      case 'added':
        fdata.push(doc)
        break
      case 'modified':
        const i = fdata.findIndex(i => i.id === doc.id)
        fdata[i] = doc
        break
      case 'removed':
        fdata = fdata.filter(i => i.id !== doc.id)
        break
      default:
        break
      }
    })

    store.commit('SET_RECIEVED_DATA_PIE', fdata)
    !store.getters.initPie && store.commit('SET_INIT_PIE')
  })
}

好像 onSnapshot()触发的次数与输入路径/pie 的次数一样

It looks like onSnapshot() fires as many times as route /pie was entered

推荐答案

从您调用 onSnapshot 的那一刻起,Firebase便会监听快照更改,直到您告诉它停止为止.因为您的代码从不告诉它停止,所以即使您离开浏览器,侦听器也会继续.然后,当您导航回/Pie 时,将附加第二个侦听器.因此,此时您的 onSnapshot 侦听器将被执行两次.

From the moment you call onSnapshot, Firebase will be listening for snapshot changes until you tell it to stop. Since your code never tells it to stop, the listener continues, even when you navigate away. Then when you navigate back to /Pie, you attach a second listener. So at that point your onSnapshot listener will be executed twice.

有两种解决方案:

  1. 检测到您已经附加了一个侦听器,并且在重新访问同一路由时不要附加它.
  2. 当您离开/Pie 时,
  3. 取消注册侦听器.您可以通过调用从 onSnapshot 返回的函数来做到这一点:

  1. Detect that you've already attached a listener, and don't attach it when you revisit the same route.
  2. Unregister the listener when you navigate away from /Pie. You do this by calling the function that is returns from onSnapshot:

var unsubscribe = db.collection('expenses').onSnapshot(...);

再后来:

unsubscribe();

另请参阅分离监听器上的Firebase文档.

Also see the Firebase documentation on detaching listeners.

这篇关于Firestore onSnapshot()方法触发多次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆