【问题标题】:How to read docs as offline and write as (online & offline) in firestore?如何在firestore中以离线方式阅读文档并以(在线和离线)方式写入?
【发布时间】:2019-10-29 07:47:25
【问题描述】:

最近我使用 Cloud Firestore 和 React Native 创建了一个简单的聊天应用程序。他们的离线和在线同步是一个相当不错的功能。

但是加载(阅读文档)非常耗时。 虽然我为每个用户(10 个用户)分页了 10 个文档,但加载消息仍然很慢,在缓慢的互联网连接中,加载消息需要 10 秒,这不是一个好的体验。

在这里,当我启用离线模式时,它会更快地加载消息(大约 3 秒)。但是这里有个问题:

现在:

可以离线加载消息,并同时保存消息(离线和在线)。

或者有没有其他更好的加载速度的方法?

当我在 firebase 中启用离线功能时,它无法在服务器中保存消息,或者我在保存消息时禁用离线,当我加载消息时它只加载离线消息。

例子:

async function getMessagesOfAllUser(userlist){
    let outstate = false, data = {};
    if (userlist !== null)
        for (let i = userlist.length - 1; i >= 0; i--) {
            outstate = await this.getMessagesOfOneUsers(userlist[i].user);
            if (outstate !== false) data = { ...data, ...outstate };
            if (i === 0) {
                this.setState({ ...this.state, ...data });
            }
        }
}

function getMessagesOfOneUser(user) {
    return db.collection('users/'+user/+'/messages').orderBy("dt", "desc").limit(10).get().then(snap => {
        let l = snap.size;
        if (l > 0) {
            const ourMessage = this.state.me + user;
            this.lastVisible = { ...this.lastVisible, ...{ [user]: snap.docs[l - 1] } };
            for (let i = 0; i < l; i++) {
                if (this.outState[ourMessage] !== undefined)
                    this.outState[ourMessage] = [...this.outState[ourMessage], snap.docs[i].data()];
                else this.outState[ourMessage] = [snap.docs[i].data()];
                if (i === l - 1) return this.outState;
            }
        }
        return false;
    });
}

【问题讨论】:

  • "但是加载(阅读文档)会耗费大量时间。"这取决于你如何阅读它。 get() 将始终尝试从服务器读取,但 onSnapshot 实际上会立即使用本地数据触发,然后才检查服务器是否有新数据。如果您显示minimal code that reproduces what you current do,会更容易为您提供帮助。
  • 我可以使用 onSnapshot 读取多个文档,特别是读取和列出消息吗?
  • 快照没有工作
  • onSnapshot 可以在DocumentReference 上调用(在这种情况下,它会给你一个DocumentSnapshot)和Query(在这种情况下它会给你一个QuerySnapshot,其中包含零个或多个 DocumentSnapshots)。如果您无法完成这项工作,请分享minimal code that reproduces where you are stuck。没有它,就很难为您提供进一步的帮助。
  • 嗨@FrankvanPuffelen,谢谢你的回复,你能看看有问题的例子吗,我已经编辑了我的问题。我的代码运行良好,它收到了 12 个用户的 10 条消息。但问题是它需要很长时间,即使在良好的互联网中也需要大约 7 秒,在糟糕的互联网中需要大约 12 秒。当我使用 firebase 调用 disableNetwrok() 函数时,大约需要 3 秒,这仍然不是很好,但是,比没有 disableNetork() 函数要好

标签: javascript firebase react-native google-cloud-firestore


【解决方案1】:

当您使用get()(不带参数)读取文档时,Firestore 客户端将始终与服务器检查以确保您获得最新数据。

您有两种选择从本地缓存中获取数据:

  1. 使用get({ source: "cache" }) (docs),它将从本地缓存中返回文档。如果本地缓存中不存在该文档,则会引发错误。在这种情况下,您仍然需要检查服务器。

  2. 使用onSnapshot() 监听器。当您附加此侦听器时,它会立即使用本地缓存中的值进行回调,就像get({ source: "cache" }) 所做的那样。但它也会与服务器检查数据是否有任何更新。如果有,它会检索更新后的文档,更新本地缓存,并使用更新后的值再次调用您的代码。

如果您在用户界面中显示数据,通常建议使用onSnapshot(),因为这意味着您的 UI 会对数据的更改做出反应。

有关这方面的更多信息,请参阅 Getting to know Cloud Firestore 系列视频中的 How do I Enable Offline Support?

【讨论】:

  • 你好@Frank 谢谢你,你可以看到我的代码,我只用onSnapshot(snap =&gt; {}) 更改了.get().then(snap=&gt;{}),但它不起作用。你能帮我把上面的代码片段从get()改成onSnapshot()吗?
  • 我也改变了,.get().get("cache") 但它出现了这个错误:Error: Query.get failed: First argument must be an object 因为我正在使用react-native-firebase,它默认启用离线支持。
  • 在这里,我检查了,它看起来 onSnapshot() 函数不是承诺并且不返回任何东西。我说的对吗?
  • 非常感谢,现在 { source: "cache" } 工作正常,现在问题是:当我离线时其他人向我发送消息。当我上网时,我无法访问他的消息。可能有问题是我只从 cache 获取消息,所以有没有更好的方法来解决这个问题。
  • 您可以统计所有用户,然后计算您收到的消息数量。然后,一旦计数器等于或大于用户数,请致电setState(...)。这样一来,您只有在收到所有用户的消息后才调用它,但之后每次更新都会调用它。
猜你喜欢
  • 2011-03-10
  • 1970-01-01
  • 1970-01-01
  • 2021-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多