【问题标题】:Admin on rest - implementing aor-realtime管理员休息 - 实施 aor-realtime
【发布时间】:2017-11-24 12:36:15
【问题描述】:

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

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

另一个问题是关于持久性的:更新流并没有一次性加载初始记录集。每次更新我都应该打电话给observer.next()吗?或者缓存更新的记录并调用 next() 与整个集合到日期。

这是我目前的尝试,但我仍然不知道如何将它连接到我的管理员/资源。

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));

【问题讨论】:

    标签: admin-on-rest


    【解决方案1】:

    如何将它与 restClient/resource 连接起来?

    只需将创建的 saga 添加到您的 Admin 组件的 custom sagas 即可。

    关于 restClient,如果您在观察者中需要它,然后将返回观察者的函数传递给它,就像您对 path 所做的那样。这实际上是在readme 中完成的。

    我应该在每次更新时调用observer.next() 吗?或者缓存更新的记录并调用 next() 与整个集合到日期。

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

    • CRUD_GET_LIST:你应该返回整个集合,更新
    • CRUD_GET_ONE: 你应该返回 params 中指定的资源(应该包含它的 id)

    【讨论】:

    • 感谢@Gildas 的回答。我还是有点困惑。让我试着解释一下我现在是如何理解它的,也许你可以告诉我我哪里错了。生成的 saga 侦听 CRUD_GET_LIST 和 CRUD_GET_ONE 事件(可选地限于单个资源)。当接收到这些事件时,它应该使用参数来启动/更新实时查询。在新事件上,我们调用observer.next()(我假设这会更新商店)。我仍然不明白 AOR 是如何知道这些事件属于哪个资源名称的,然后我如何在 中为该资源添加 标记。再次感谢!
    • aor-realtime 知道哪个资源,因为您为收到的特定参数(类型、资源、参数)返回了一个观察者。然后它使用这些参数从 aor 触发相关的 redux 操作。我不确定我是否理解您关于 Resource 的第二个问题。只需像您通常对其他资源所做的那样声明它吗?
    • 我现在得到了第一部分!对于我的第二个问题:如果资源集合由 saga 管理,我的 restClient 在收到对该资源的请求时应该做什么?我可能应该在一开始就澄清一下,我将这个由 firebase 支持的资源与其他由 rest-api 支持的资源混合在一起
    • 我假设由 firebase 后端管理的资源也由您的 restClient 管理以进行版本等?
    • 不,firebase 资源是只读的。我不通过 AOR 编辑它们。我拥有的其他资源由我的 restClient 管理以进行 CRUD 操作
    【解决方案2】:

    这是我在@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));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多