Falcor-未缓存深层嵌套引用

时间:2019-02-19 16:24:15

标签: falcor

当我请求包含嵌套引用的路由时,我发现Falcor客户端出现问题。

这里是一个例子:

model.get调用中考虑来自Falcor服务器的以下JsonGraph响应

{
  "todos": {
    "0": { "$type": "ref", "value": ["todosById", "id_0"] },
    "1": { "$type": "ref", "value": ["todosById", "id_1"] },
    "length": 2
  },
  "todosById": {
    "id_0": {
      "name": "get milk",
      "label": { "$type": "ref", "value": ["labelsById", "lbl_0"] },
      "completed": false
    },
    "id_1": {
      "name": "do the laundry",
      "label": { "$type": "ref", "value": ["labelsById", "lbl_1"] },
      "completed": false
    }
  },
  "labelsById": {
    "lbl_0": { "name": "groceries" },
    "lbl_1": { "name": "home" }
  }
}

当我使用以下路径调用model.get时,以上所有jsonGraph结果都应该在缓存中:

model.get(['todos', {from: 0, to: 1}, ['completed', 'label', 'name']])

但是,手动访问缓存,我​​可以看到todostodosById在缓存中,但没有labelsById

我不确定,但是labelsById好像不在二级缓存中,因为它是第二级引用?

我在这里丢失了什么吗,还是Falcor缓存的预期行为? 是否有任何方法可以强制labelsById进入缓存,因此不会提出其他数据源请求?

感谢您的帮助!

这个问题可以在这个小项目中重现: https://github.com/ardeois/falcor-nested-references-cache-issue

更新

感谢@ james-conkling回答,可以通过执行以下model.get来缓存json图:

model.get(
  ['todos', {from: 0, to: 1}, ['completed', 'name']],
  ['todos', {from: 0, to: 1}, 'label', 'name']
);

但是,在服务器端,Falcor路由器会两次调用todos[{integers:indices}]路由。这可能会对您的Falcor服务器所面对的API或数据库调用产生影响。

1 个答案:

答案 0 :(得分:0)

在路径集['todos', {from: 0, to: 1}, ['completed', 'label', 'name']]中,以completedname键结尾的路径终止于一个原子。但是以label键结尾的路径终止于引用。如果您想真正遵循该参考,则必须将其作为第二条路径:

[
   ['todos', {from: 0, to: 1}, ['completed', 'name']],
   ['todos', {from: 0, to: 1}, 'label', 'name']
]

通常,所有路径都应终止于一个原子,而不应终止于ref。我不确定终止于ref的路径的预期行为是什么,或者不确定其定义是否正确(如your other question所述,行为已从v0更改为v1)。

model.get(...paths)调用可以采用多个pathSet数组,因此重写查询应该和

一样简单。
model.get(
  ['todos', {from: 0, to: 1}, ['completed', 'name']],
  ['todos', {from: 0, to: 1}, 'label', 'name']
);

编辑

如以下注释中所述,由于路由器处理程序一次只能解析单个pathSet,因此具有多个pathSet的GET请求可能导致对上游支持服务/数据库的多个请求。一些可能的解决方案:

使用一条路径

使用单个路径['todos', range, ['completed', 'name', 'label'], 'name']重写请求。从技术上讲,此请求除了todos.n.completed.name(不存在)之外,还请求todos.n.label.nametodos.n.label.name(不存在)。

但是,如果路由器处理程序为比匹配路径短的路径返回pathValues,则应将较短的pathValues合并到jsonGraph缓存中。例如。匹配todos.0.completed.name时,返回{ path: ['todos', 0, 'completed'], value: true },匹配todos.0.label.name时,返回{ path: ['todos', 0, 'label', 'name'], value: 'First TODO' }

这可能是最简单的方法,但是这意味着您的查询在语义上并不是真正正确的(您故意在询问不存在的路径)。

分批路由器发出的上游请求

在路由器中,将上游请求批处理到后备服务/数据库。这并不总是那么简单。一种可能的方法是使用Facebook的data-loader,其编写目的是解决带有GraphQL路由器的等效问题,但不一定要与GraphQL捆绑在一起。另一种方法可以使用自定义的reducer函数来合并使用同一滴答声发出的请求(例如here)。

重写您的架构

这样,需要同时请求的所有路径都具有相同的长度。不过,:shrug并非总是如此。

相关问题