【问题标题】:How to reuse GraphQL individual query API to get the list?如何重用 GraphQL 单个查询 API 来获取列表?
【发布时间】:2018-11-15 04:02:59
【问题描述】:

我正在尝试获取模型列表。

首先我创建了一个模型查询 API。现在我想通过提供ids 来获取列表。

我知道我可以在getModelById 上使用Promise.all 并对我再次获得的每个结果进行一些处理。

但是有没有办法重用单个模型查询 API?谢谢

const ModelType = new GraphQLObjectType({
  name: 'Model',
  fields: {
    id: { type: GraphQLString },
    // ...
  }
});

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: () => ({
    model: {
      type: ModelType,
      args: {
        id: { type: GraphQLString }
      },
      resolve(parentValue, args) {
        const { id } = args;
        return getModelById(id).then(model => doSomeProcessing(model));
      }
    },

    models: {
      type: new GraphQLList(ModelType),
      args: {
        ids: { type: new GraphQLList(GraphQLString) }
      },
      resolve(parentValue, args) {
        const { ids } = args;
        // here I know I can use Promise.all on getModelById and do my doSomeProcessing again for each result I got,
        // but is there a way to reuse the model query above? Thanks
      }
    }
  })
});

【问题讨论】:

    标签: javascript node.js graphql


    【解决方案1】:

    您不能在另一个解析器中引用现有解析器。您可以重用逻辑的唯一方法是将其抽象为一个由两个解析器调用的单独函数。例如:

    const getProcessedModelById = (id) => {
      return getModelById(id).then(model => doSomeProcessing(model))
    }
    
    // model
    resolve(parentValue, args) {
      return getProcessedModelById(args.id)
    }
    
    // models
    resolve(parentValue, args) {
      return Promise.all(args.ids.map(id => getProcessedModelById(args.id)))
    }
    

    根据您对模型进行的处理的种类,可以通过Model 类型的字段解析器来完成。假设您的Model 类型有两个字段——firstNamelastName,但您的模型返回一个名为name 的字段。你的doSomeProcessing 只是取了这个名字并将它分成firstNamelastName

    function doSomeProcessing (model) {
      const names = model.name.split(' ')
      return { firstName: names[0], lastName: names[1] }
    }
    

    您的解析器可以返回 getModelById 返回的任何内容,而不是这样做。然后就可以在每个字段的解析器中封装“处理”逻辑了:

    // firstName field
    resolve (parentValue) {
      return parentValue.name.split(' ')[0]
    }
    
    // lastName field
    resolve (parentValue) {
      return parentValue.name.split(' ')[1]
    }
    

    这种方法的优点是“处理”实际上不会发生,除非客户端请求该字段。在这个非常简单的示例中,解析lastName 字段并不昂贵,但可能并非总是如此。它还非常巧妙地封装了从底层数据层派生的字段的逻辑。但是,它也可能最终变得更昂贵(例如,假设 split 调用本身很昂贵......现在我们调用该方法两次而不是一次)。

    【讨论】:

    • 是的,这是我目前的方式,我只是想知道是否有 GraphQL 方式,因为 GraphQL 对我来说仍然有太多的魔力。谢谢你告诉我!
    • @HongboMiao 用一些额外的想法更新了答案:)
    猜你喜欢
    • 2021-03-11
    • 2019-10-25
    • 2021-04-26
    • 2020-03-30
    • 2018-07-09
    • 2016-09-20
    • 2018-06-03
    • 2020-08-23
    • 1970-01-01
    相关资源
    最近更新 更多