管理员休息 - 实施 aor-realtime

Admin on rest - implementing aor-realtime

我很难理解如何实施 aor-realtime(尝试将其与 firebase 一起使用;只读,不能写入)。

我卡住的第一个地方:这个库生成了一个 saga,对吧?我如何将它与 restClient/resource 联系起来?我有一些自定义的 sagas 可以提醒我错误,但有一个主要 restClient/resource 支持这些。那些传奇只是处理一些副作用。在这种情况下,我只是不明白客户端的角色是什么,以及它如何与生成的传奇(或反之亦然)进行交互

另一个问题与持久性有关:更新流进来并且初始记录集没有一次性加载。我应该在每次更新时调用 observer.next() 吗?或缓存更新后的记录并使用最新的整个集合调用 next()

这是我目前尝试做的后者,但我仍然不知道如何将它连接到我的 Admin/Resource。

import realtimeSaga from 'aor-realtime';
import { client, getToken } from '../firebase';
import { union } from 'lodash'

let cachedToken 
const observeRequest = path => (type, resource, params) => {
    // Filtering so that only chats are updated in real time
    if (resource !== 'chat') return;

    let results = {}
    let ids = []

    return {
        subscribe(observer) {
            let databaseRef = client.database().ref(path).orderByChild('at')

            let events = [ 'child_added', 'child_changed' ]

            events.forEach(e => {
                databaseRef.on(e, ({ key, val }) => {
                    results[key] = val()
                    ids = union([ key ], ids)
                    observer.next(ids.map(id => results[id]))
                })  
            })          
            const subscription = {
                unsubscribe() {
                    // Clean up after ourselves
                    databaseRef.off()
                    results = {}
                    ids = []
                    // Notify the saga that we cleaned up everything
                    observer.complete();
                }
            };

            return subscription;
        },
    };
};

export default path => realtimeSaga(observeRequest(path));

How do I connect that with a restClient/resource?

只需将创建的 saga 添加到 Admin 组件的 custom sagas

关于 restClient,如果您在您的观察者中需要它,那么将 return 您的观察者的函数传递给它,就像您对 path 所做的那样。 readme.

实际上就是这样做的

Should I be calling observer.next() with each update? or cache the updated records and call next() with the entire collection to-date.

这取决于 type 参数,它是 admin-on-rest 提取类型之一:

  • CRUD_GET_LIST:你应该return整个collection,更新
  • CRUD_GET_ONE: 你应该return参数中指定的资源(应该包含它的id)

这是我在@gildas 的指导下提出的解决方案:

import realtimeSaga from "aor-realtime";
import { client } from "../../../clients/firebase";
import { union } from "lodash";
const observeRequest = path => {      
  return (type, resource, params) => {
    // Filtering so that only chats are updated in real time
    if (resource !== "chats") return;

    let results = {}
    let ids = []

    const updateItem = res => {
      results[res.key] = { ...res.val(), id: res.key }
      ids = Object.keys(results).sort((a, b) => results[b].at - results[a].at)
    }

    return {
      subscribe(observer) {
        const { page, perPage } = params.pagination
        const offset = perPage * (page - 1)

        const databaseRef = client
            .database()
            .ref(path)
            .orderByChild("at")
            .limitToLast(offset + perPage)

        const notify = () => observer.next({ data: ids.slice(offset, offset + perPage).map(e => results[e]), total: ids.length + 1 })

        databaseRef.once('value', snapshot => {
          snapshot.forEach(updateItem)
          notify()
        })

        databaseRef.on('child_changed', res => {
          updateItem(res)
          notify()    
        })


        const subscription = {
          unsubscribe() {
            // Clean up after ourselves
            databaseRef.off();
            // Notify the saga that we cleaned up everything
            observer.complete();
          }
        };

        return subscription;
      }
    };
  }
};

export default path => realtimeSaga(observeRequest(path));