如何在 Flux 应用程序中处理嵌套的 API 响应? [英] How do I handle nested API responses in a Flux application?

查看:24
本文介绍了如何在 Flux 应用程序中处理嵌套的 API 响应?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将一个现有的应用程序移植到 Flux,我对一个主题有点困惑.假设我有几个返回两级或三级嵌套对象的 API 端点.

I'm porting an existing app to Flux and I'm a bit confused about one topic. Say I have several API endpoints that return two- or three-level nested objects.

例如,GET/articles 可能会返回架构的 JSON 响应

For example, GET /articles may return a JSON response of schema

articles: article*

article: {
  author: user,
  likers: user*
  primary_collection: collection?
  collections: collection*
}

collection: {
  curator: user
}

如您所见,有各种不同级别的用户:

As you see, there are all kinds of users at different levels of nesting:

  • articles[i].author
  • articles[i].likers[i]
  • articles[i].primaryCollection.curator
  • articles[i].collections[i].curator

如果我想在任何时候获取文章时使用新数据更新 UserStore,我必须编写一个可怕的方法来检查文章 API 响应上的所有嵌套实体.此外,还会有很多重复,因为还有其他具有不同架构的 API 端点,有时文章会嵌入用户内部(例如 GET/user/published).

If I want to update UserStore with fresh data any time articles are fetched, I'd have to write a monstrous method that checks all nested entities on article API response. Moreover, there would be a lot of duplication because there are also other API endpoints with different schemas, and sometimes articles are embedded inside users (e.g. GET /user/published).

是否有一种更简洁的方式让 Flux 商店从所有 API 响应中提取嵌套实体?

Is there a cleaner way for Flux stores to extract nested entities out of all API responses?

推荐答案

Jing Chen(Flux 的创建者和布道者之一)建议的方法) 是为了在 API 响应到达 Stores 之前将它们展平.我写了一个小库来做到这一点:它规范化

An approach suggested by Jing Chen (one of Flux creators and evangelists) was to flatten API responses before they reach the Stores. I wrote a small library that does just that: it normalizes

[{
  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'
      }
    }
  }
}

(注意没有重复,结构是扁平的.)

(Note there is no duplication and the structure is flat.)

Normalizr 让您:

Normalizr lets you:

  • 在其他实体、对象和数组中嵌套实体
  • 组合实体模式以表达任何类型的 API 响应
  • 自动合并具有相同 ID 的实体(如果它们不同,则会发出警告)
  • 使用自定义 ID 属性(例如 slug)

要使用它,您需要定义实体和嵌套规则并使用它们来转换 JSON:

To use it, you need to define your entities and nesting rules and use them to transform 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 之前对其进行标准化.Stores 只需要从相应的字典中更新自己:

This allows you to normalize any XHR response before passing it to Flux Dispatcher. The Stores will only need to update themselves from the corresponding dictionary:

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

这篇关于如何在 Flux 应用程序中处理嵌套的 API 响应?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆