如何通过 redux-observable/rxjs 使用 Firestore 实时更新(onSnapshot)?

Posted

技术标签:

【中文标题】如何通过 redux-observable/rxjs 使用 Firestore 实时更新(onSnapshot)?【英文标题】:How to use Firestore realtime updates (onSnapshot) with redux-observable/rxjs? 【发布时间】:2018-11-12 07:01:51 【问题描述】:

我可以使用普通 Firestore 查询设置 redux-observable

export const getStatementsEpic = (action$, store) => 
  return action$.ofType(GET_STATEMENTS)
    .filter(() => 
      const state = store.getState()
      return state.auth.user
    )
    .mergeMap(() => 
      console.log('action', store.getState().auth.user.uid)
      const db = firebase.firestore()
      db.settings( timestampsInSnapshots: true )
      const query = db.collection('users')
        .doc(store.getState().auth.user.uid)
        .collection('statements')
        .orderBy('uploadedOn', 'desc')
        .limit(50)
      return query.get().then(snapshot => 
        console.log('Should have gotten snapshot')
        return getStatementsSnapshot(snapshot)
      )
    )

但我想将其转换为实时,我尝试更改

return query.get().then(snapshot => 

return query.onSnapshot(snapshot => 

但它不起作用......我想这不是一个承诺?我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

你是对的,onSnapshot 方法不返回承诺。相反,它返回一个可用于取消订阅更改通知的函数。在调用取消订阅函数之前,每次文档更改时都会调用传递给onSnapshot 方法的回调。 (documentation 表示回调也将立即与当前文档内容一起调用。)

onSnapshot 这样多次使用回调函数的函数可以使用fromEventPattern 函数“转换”为可观察对象。 fromEventPattern 接受两个函数作为参数。您传递的第一个函数需要调用onSnapshot,将一个 RxJS 定义的处理程序作为回调传递给它。您传递的第二个函数需要调用onSnapshot 返回的取消订阅函数。当你订阅 observable 时,RxJS 将调用第一个函数(即在你的史诗中使用它)。当你取消订阅 observable 时,RxJS 会调用第二个函数。

这是一个更新代码以使用 fromEventPattern 和新的 RxJS 管道的示例:

export const getStatementsEpic = (action$, state$) => action$.pipe(
  ofType(GET_STATEMENTS),
  withLatestFrom(state$),
  filter(([action, state]) => state.auth.user),
  mergeMap(([action, state]) => 
    const db = firebase.firestore()
    db.settings( timestampsInSnapshots: true )
    return fromEventPattern(
      handler => db.collection('users')
        .doc(state.auth.user.uid)
        .collection('statements')
        .orderBy('uploadedOn', 'desc')
        .limit(50)
        .onSnapshot(handler),
      (handler, unsubscribe) => unsubscribe(),
    ).pipe(
      map(getStatementsSnapshot),
      takeUntil(action$.pipe(
        ofType(STOP_GET_STATEMENTS),
      )),
    )
  ),
)

请注意,我已将takeUntil 引入快照流。没有它(或类似的东西),快照流将永远不会结束。另一个可能的更改是使用switchMap 而不是mergeMap。如何退订取决于您的用例。

【讨论】:

以上是关于如何通过 redux-observable/rxjs 使用 Firestore 实时更新(onSnapshot)?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过android上的ADB命令通过pc拨打电话?

如何通过 DBLINK 通过 DBLINK 调用 SELECT?

如何使用jquery通过.load通过跨域获取HTML元素的值

如何通过 Windows Azure 通过 GCM 通过唯一 ID 发送特定 Android 设备的通知?

如何通过方法(不是api)通过identityserver4获取访问令牌?

如何通过主机从外部通过 SSH 连接到 VirtualBox 来宾? [关闭]