【问题标题】:Is there any method like onDisconnect() in firestore like there is in realtime database?Firestore中是否有像实时数据库中的onDisconnect()这样的方法?
【发布时间】:2018-08-13 22:56:15
【问题描述】:

我想在实时数据库中检查用户的在线状态,我曾经在 onDisconnect() 的帮助下检查过这个,但现在我已经转移到 firestore 并且在其中找不到任何类似的方法。

【问题讨论】:

标签: firebase firebase-realtime-database google-cloud-firestore


【解决方案1】:

据此onDisconnect

onDisconnect 类最常用于管理应用程序中的状态,它有助于检测连接的客户端数量以及其他客户端何时断开连接。

为了能够在firestore中使用presence,您需要将firestore与实时firebase连接(没有其他方式)。

请查看此以获取更多信息:

https://firebase.google.com/docs/firestore/solutions/presence

【讨论】:

    【解决方案2】:

    注意:这个解决方案不是特别有效

    在我的脑海中(阅读:我没有考虑过警告),你可以做这样的事情:

    const fiveMinutes = 300000 // five minutes, or whatever makes sense for your app
    
    // "maintain connection"
    setInterval(() => {
      userPresenceDoc.set({ online: new Date().getTime() })
    }, fiveMinutes)
    

    然后,在每个客户端上...

    userPresenceDoc.onSnapshot(doc => {
      const fiveMinutesAgo = new Date().getTime() - fiveMinutes
      const isOnline = doc.data().online > fiveMinutesAgo
      setUserPresence(isOnline)
    })
    

    您可能希望检查存在的代码使用的时间间隔比维护连接的代码使用的时间间隔多一点,以解决网络延迟等问题。

    关于费用的说明

    因此,很明显,在某人断开连接与其他客户端识别到该断开连接之间可能会有很大的延迟。您可以通过增加写入 Firestore 的频率来减少延迟时间,从而增加您的成本。运行这些数字,假设单个客户端连接连续运行一个月,我得出了以下不同时间间隔的成本:

    Interval     Cost/User/Month
    ----------------------------
    10m          $0.007776
     5m          $0.015552
     1m          $0.07776
    10s          $0.46656
     5s          $0.93312
     1s          $4.6656
    

    1 秒的时间间隔相当昂贵,对于一个拥有 10,000 名用户且整个月都保持打开应用程序的系统来说,每月需要 46,656 美元。对于相同数量的用户,间隔 10 分钟仅需 77.76 美元/月。一分钟、10,000 名用户和每位用户每天仅使用四个小时的应用程序的更合理的时间间隔为 129.60 美元/月。

    【讨论】:

    • 很高兴您添加了计算!可能值得注意的是,考虑到他们 24/7 都在应用内花费,每个用户每月约 5 美元并不是很多,您将希望从这类用户身上获利。 :P
    【解决方案3】:

    没有等价物。 Firestore SDK 目前没有像实时数据库 SDK 那样的在线状态管理。

    相反,您可能希望将实时数据库 onDisconnect() 与 Cloud Functions 结合使用,以便在客户端与 RTDB 断开连接时启动一些工作。您会假设您的应用可能同时失去了与 Firestore 的连接。

    【讨论】:

    • 您是否有至少适用于 Realtime Db 的可用 node.js 代码?我正在使用文档代码,但它们没有更新离线更改
    【解决方案4】:

    试试这个,但这种方法有点不合时宜,因为我们不能在 firestore 中使用 onDisconnected。据我所知,实时数据库使用安全的 WebSocket 技术,所以这就是为什么 onDisconnected 有它的原因

    但是你可以使用realtime database 可以在cloud functions 中实现 给update the firestore data,

    functions.database.ref('users/{userId}').onUpdate()
    

    客户端某处:

    firebase.database()
      .ref('.info/connected')
      .on('value', async (snap) => {
        if (snap.val() === true) {
          // Update the online status in RTDB 
          await firebase.database()
            .ref(`users/${credentials.user.uid}/`)
            .set({
              online_status: true,
              start_online: firebase.database.ServerValue.TIMESTAMP
            });
    
          // OnDisconnect
          firebase.database()
            .ref(`users/${credentials.user.uid}/`)
            .onDisconnect()
            .set({
              online_status: false,
              last_online: firebase.database.ServerValue.TIMESTAMP
            });
        }
      });
    

    在 cloudfunctions 中(这将在更新时触发)

    export const onUserOnlineStatusChanged = functions.database.ref('users/{userId}').onUpdate((event: functions.Change<functions.database.DataSnapshot>, context: functions.EventContext) => {
      return event.after.ref.once('value')
        .then((dataSnapshot) => dataSnapshot.val()) // Get the latest value from the Firebase Realtime database
        .then((value: any) => {
          // Update the value from RTDB to Firestore
          console.log('value.online_status', value.online_status);
    
          if (value.online_status == true) {
            // Set the value to the firestore
            admin.firestore()
              .collection('users_info')
              .doc(context.params.userId) // Get document by the userId / Or use .where
              .set({
                online_status: value.online_status,
                updated_at: new Date
              }, {
                mergeFields: [
                  'online_status',
                  'updated_at'
                ]
              });
    
            // Add code if necessary (when the online_status is true)
    
          } else if (value.online_status == false) {
            // Set the value to the firestore
            admin.firestore()
              .collection('users_info')
              .doc(context.params.userId)  // Get document by the userId / Or use .where
              .set({
                online_status: value.online_status,
                updated_at: new Date
              }, {
                mergeFields: [
                  'online_status',
                  'updated_at'
                ]
              });
    
            // Add code if necessary (when the online_status is false)
          }
    
        });
    });
    

    从云功能更新到 Firestore 大约需要 1 或 2 秒

    【讨论】:

      【解决方案5】:

      没有直接的方法来做这件事,但这个技巧帮助我实现了这个断开连接的监听器。 window.addEventListener("beforeunload", async function (e) { e.preventDefault(); await firestoreRef.doc("doc-ref").update({ online: false }); });

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-10
        • 1970-01-01
        • 1970-01-01
        • 2020-01-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多