繁体   English   中英

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

[英]How to use Firestore realtime updates (onSnapshot) with redux-observable/rxjs?

我可以使用普通 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 => {

但它不起作用......我猜这不是promise? 我该如何解决这个问题?

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

onSnapshot这样onSnapshot使用回调函数的函数可以使用fromEventPattern函数“转换”为一个observable。 fromEventPattern将两个函数作为参数。 您传递的第一个函数需要调用onSnapshot ,并将其作为回调传递给RxJS定义的处理程序。 您传递的第二个函数需要调用onSnapshot返回的unsubscribe函数。 当您订阅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 如何取消订阅仅取决于您的使用案例。

This might be a little bit late, but the easiest way is to create Observable rather than using fromEventPattern since firebase event listener model were similar with rxjs Teardown model.

这是使用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 })
      return new Observable(subscriber => db.collection('users')
        .doc(state.auth.user.uid)
        .collection('statements')
        .orderBy('uploadedOn', 'desc')
        .limit(50)
        .onSnapshot(subscriber.next, subscriber.error)
      );
    })
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM