【问题标题】:How to use Firestore realtime updates (onSnapshot) with redux-observable/rxjs?如何通过 redux-observable/rxjs 使用 Firestore 实时更新(onSnapshot)?
【发布时间】: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 => {

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

【问题讨论】:

    标签: reactjs firebase redux google-cloud-firestore redux-observable


    【解决方案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。如何退订取决于您的用例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-13
      • 2020-06-05
      • 2019-12-16
      • 1970-01-01
      • 2021-10-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多