如何处理 Flux 应用程序中的嵌套 API 响应?
Posted
技术标签:
【中文标题】如何处理 Flux 应用程序中的嵌套 API 响应?【英文标题】:How do I handle nested API responses in a Flux application? 【发布时间】:2014-10-14 01:45:44 【问题描述】:我正在将现有应用程序移植到 Flux,但我对一个主题有点困惑。 假设我有几个返回两级或三级嵌套对象的 API 端点。
例如,GET /articles
可能会返回 schema 的 JSON 响应
articles: article*
article:
author: user,
likers: user*
primary_collection: collection?
collections: collection*
collection:
curator: user
如你所见,不同层次的用户有各种各样的嵌套:
articles[i].author
articles[i].likers[i]
articles[i].primaryCollection.curator
articles[i].collections[i].curator
如果我想在任何时候获取文章时用新数据更新UserStore
,我必须编写一个可怕的方法来检查文章 API 响应中的所有嵌套实体。此外,还会有很多重复,因为还有其他 API 端点具有不同的架构,有时文章会嵌入到用户内部(例如GET /user/published
)。
Flux 商店是否有一种更简洁的方法来从所有 API 响应中提取嵌套实体?
【问题讨论】:
【参考方案1】:Jing Chen(Flux 的创建者和传播者之一)建议的一种方法是在 API 响应到达 Store 之前将其展平。我写了一个小型库来做到这一点:它规范化
[
id: 1,
title: 'Some Article',
author:
id: 1,
name: 'Dan'
,
id: 2,
title: 'Other Article',
author:
id: 1,
name: 'Dan'
]
到
result: [1, 2],
entities:
articles:
1:
id: 1,
title: 'Some Article',
author: 1
,
2:
id: 2,
title: 'Other Article',
author: 1
,
users:
1:
id: 1,
name: 'Dan'
(注意没有重复,结构是扁平的。)
Normalizr 让您:
在其他实体、对象和数组中嵌套实体 结合实体模式来表达任何类型的 API 响应 自动合并具有相同 ID 的实体(如果它们不同,则会发出警告) 使用自定义 ID 属性(例如 slug)要使用它,您需要定义实体和嵌套规则并使用它们来转换 JSON:
var normalizr = require('normalizr'),
normalize = normalizr.normalize,
Schema = normalizr.Schema,
arrayOf = normalizr.arrayOf;
// First, define a schema:
var article = new Schema('articles'),
user = new Schema('users'),
collection = new Schema('collections');
// Define nesting rules:
article.define(
author: user,
collections: arrayOf(collection)
);
collection.define(
curator: user
);
// Usage:
// Normalize articles
var articlesJSON = getArticleArray(),
normalized = normalize(articlesJSON, arrayOf(article));
// Normalize users
var usersJSON = getUsersArray(),
normalized = normalize(usersJSON, arrayOf(user));
// Normalize single article
var articleJSON = getArticle(),
normalized = normalize(articleJSON, article);
这允许您在将任何 XHR 响应传递给 Flux Dispatcher 之前对其进行规范化。 商店只需要从相应的字典中更新自己:
// UserStore
UserStore.dispatchToken = AppDispatcher.register(function (payload)
var action = payload.action;
switch (action.type)
// you can add any normalized API here since that contains users:
case ActionTypes.RECEIVE_ARTICLES:
case ActionTypes.RECEIVE_USERS:
// Users will always be gathered in action.entities.users
mergeInto(_users, action.entities.users);
UserStore.emitChange();
break;
);
// ArticleStore
AppDispatcher.register(function (payload)
var action = payload.action;
switch (action.type)
// you can add any normalized API here since that contains articles:
case ActionTypes.RECEIVE_ARTICLES:
// Wait for UserStore to digest users
AppDispatcher.waitFor([UserStore.dispatchToken]);
// Articles will always be gathered in action.entities.articles
mergeInto(_articles, action.entities.articles);
ArticleStore.emitChange();
break;
);
【讨论】:
规范化如何处理需要传回服务器以进行 UPDATE/POST 的数据? 你也可以使用 normalizr 去规范化。以上是关于如何处理 Flux 应用程序中的嵌套 API 响应?的主要内容,如果未能解决你的问题,请参考以下文章