【问题标题】:snapshot.docChanges() not working in Firebase Firestoresnapshot.docChanges() 在 Firebase Firestore 中不起作用
【发布时间】:2018-07-09 20:00:27
【问题描述】:

我们遇到了监听器在错误时间触发的问题。我试图通过以下方式查看元数据更改:

firebase.firestore().collection('Users').doc($scope.user.uid).collection($scope.longLanguage).doc('Missing_Word').onSnapshot(function(snapshot) {
        snapshot.docChanges().forEach(function(change) {
          console.log(change.doc.data());
        })

这是错误信息:

Uncaught TypeError: snapshot.docChanges is not a function

我也尝试打开 metadataChanges:

firebase.firestore().collection('Users').doc($scope.user.uid).collection($scope.longLanguage).doc('Missing_Word').onSnapshot({includeMetadataChanges: true}, function(snapshot) {
    snapshot.docChanges().forEach(function(change) {
      console.log(change.doc.data());
    })

我们在documentation 附近写了这篇文章。知道我们做错了什么吗?

【问题讨论】:

    标签: javascript firebase google-cloud-firestore


    【解决方案1】:

    onSnapshot() 接受一个接收DocumenSnapshot 对象的回调函数。 DocumentSnapshot 没有 docChanges 方法。

    看起来您希望回调包含 QuerySnapshot,而它确实包含 docChanges。当您对集合执行查询时,您会收到 QuerySnapshot,而不是您在此处显示的单个文档。

    【讨论】:

    • 文档显示了针对文档而不是集合的查询。我们的代码几乎是从文档中剪切和粘贴的。
    • 我的意思是您的代码正在查询文档,而不是集合。文档查询与集合查询的工作方式不同。请查阅文档以了解每种情况下的 API。
    • 我无法让 docChanges() 处理集合查询。我的代码是db.collection('users') .doc(uid) .collection('photos_selling') .onSnapshot(querySnapshot => { let changes = querySnapshot.docChanges(); console.log(changes); });
    【解决方案2】:

    以下示例在此处的文档中 https://firebase.google.com/docs/firestore/query-data/listen#view_changes_between_snapshots

    在浏览器中:

    db.collection("cities").where("state", "==", "CA")
        .onSnapshot(function(snapshot) {
            snapshot.docChanges().forEach(function(change) {
                if (change.type === "added") {
                    console.log("New city: ", change.doc.data());
                }
                if (change.type === "modified") {
                    console.log("Modified city: ", change.doc.data());
                }
                if (change.type === "removed") {
                    console.log("Removed city: ", change.doc.data());
                }
            });
        });
    
    

    在nodejs中

    let observer = db.collection('cities').where('state', '==', 'CA')
      .onSnapshot(querySnapshot => {
        querySnapshot.docChanges().forEach(change => {
          if (change.type === 'added') {
            console.log('New city: ', change.doc.data());
          }
          if (change.type === 'modified') {
            console.log('Modified city: ', change.doc.data());
          }
          if (change.type === 'removed') {
            console.log('Removed city: ', change.doc.data());
          }
        });
      });
    
    

    所以请注意.onSnapshots 都在Firestore.CollectionReference 上,而不是DocumentReference 上(doc() 之后)

    【讨论】:

    • 如何检测它是新快照(我触发了结果为零的新查询 - 所以根本不调用 docChanges().forEach())还是旧快照中的 docChanges?
    【解决方案3】:

    需要注意的其他事项:这似乎取决于您使用的 Firebase JS SDK 版本。当然,正如其他答案所指出的那样,请务必检查您是在文档还是集合上调用onSnapshot。但是关于在集合上调用它,我最近使用的是 4.13.1 和 docChanges 不是一个函数,但是当我升级到 v.7.15 时,我不得不将我所有的 snapshot.docChanges 更改为 snapshot.docChanges()

    release notes 也证实了这一点。在 v.5.0 中,他们将 docChanges 更改为一个函数。 See here 例如,来自带有 4.13.1 标签的分支,其中 docChanges 不是函数。

    【讨论】:

      【解决方案4】:

      如果有人收到此错误消息并正在寻找易于理解的答案:

      对集合的查询会返回给您一个列表文档。 在这种情况下,您使用 docChanges().forEach(change => {

      遍历列表
      db.collection("cities").onSnapshot(querySnapshot => { //onSnapshot on collection
         querySnapshot.docChanges().forEach(change => {
           //do whatever you want here...
         });
      });
      

      对文档的查询会返回给您一个单个文档。 在这种情况下,您不需要 docChanges(),因为单个文档的快照没有“docChanges”函数

      db.collection("cities").doc("someId") //onSnapshot on a document
      .onSnapshot((doc) => {
          console.log("Current data: ", doc.data());
      });
      

      【讨论】:

        【解决方案5】:

        对于 firebase ^6.6.2:

        docChanges() 函数只能针对集合运行

        另外onSnapshot默认可能不会返回这个函数,但是它接受一个选项

        { includeMetadataChanges: true }
        

        示例:

        firebase
          .firestore()
          .collection("/restaurant")
          .onSnapshot({ includeMetadataChanges: true }, (resp) =>
            console.log(resp.docChanges())
          );
        

        【讨论】:

          【解决方案6】:

          这是使用docChanges()方法的简单方法:

                  db.collection("cities").onSnapshot(querySnapshot => {
          
                      let changes = querySnapshot.docChanges();
                      for (let change of changes) {
                          var data = change.doc.data();
                          console.log(data);
                      }
          
          
                  });
          

          【讨论】:

            【解决方案7】:

            去掉docChanges()的括号,就是docChanges

            【讨论】:

            • 不正确,它是一个函数。请修正或删除您的误导性答案。
            • 如果您谈论的是在集合快照上调用的 docChanges,请确保检查您使用的 Firebase js sdk 版本。有关更多信息,请参阅my answer
            猜你喜欢
            • 2019-11-11
            • 2020-05-08
            • 2020-08-24
            • 1970-01-01
            • 1970-01-01
            • 2023-02-09
            • 2021-05-04
            • 2020-06-24
            • 1970-01-01
            相关资源
            最近更新 更多