RootQuery Resolve:在单独的js文件中调用服务

时间:2019-01-25 16:43:20

标签: graphql

我可以使用javascript,但我对GraphQL非常陌生。我目前有这个GraphQL结构,它正在工作。我在网上找到了有关如何将不同类型组织到SRP文件中的示例。但是,我找不到解决方法,因为它需要功能。

GraphQL:

const RootQueryType = new GraphQLObjectType({
   name: 'RootQueryType',

   fields: {

    ownerData: {
        type: OwnerType,
        description: 'Get all owners',
        args:{key: {type: GraphQLString} },
        resolve: (obj, args) => {
            const url = 'http://localhost:5001/api/.../' + args.key
            return fetch(url)
                .then(response => {
                    return response.json()
                })
                .then(json => {
                    return transform(json)
                })
                .catch(err => {
                    console.trace(err)
                })
        }
    },
    carData: {
        type: carType,
        description: 'Get owned vehicles',
        args:{key: {type: GraphQLString} },
        resolve: (obj, args) => {
            const url = 'http://localhost:6001/api/.../' + args.key
            return fetch(url)
            .then(response => {
                return response.json()
            })
            .then(json => {
                return transform(json)
            })
            .catch(err => {
                console.trace(err)
            })  
        }
    },
}
})

我可以将服务调用移到单独的文件中,但是由于需要函数,因此不确定如何构造解析。

会是这样吗?

const VehicleService = require('./ExternalServices/Vehicles');
.....snip...
resolve: (obj, args) => { VehicleService.GetVehicles() }

2 个答案:

答案 0 :(得分:1)

一般来说,我发现保持代码井井有条的最佳方法是将所有业务逻辑放在其他地方,并初始化为context对象。如果您直接使用graphql-js(如果您使用的是类似apollo-server的方式,则设置会有所不同,但是context仍然是正确的选择):

graphql.js摘录 (数据加载器是此处的SRP逻辑)

const { graphql } = require('graphql');
const dataloaders = require('./dataloaders');
const typeDefs = require('./type-definitions')
const schema = require('./schema')

exports.query = (whatever, args) => {
  const context = {};
  context.requestId = 'uuid-something';
  context.loaders = dataloaders.initialize({ context });

  return graphql(schema, query, null, context)
}

schema.js摘录

const RootQueryType = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    ownerData: {
      type: OwnerType,
      description: 'Get all owners',
      args:{key: {type: GraphQLString} },
      resolve: (obj, args, context) => {
        const key = args.key;
        return context.loaders.owner({ key });
      }
    }
  }
});

dataloaders.js摘录

exports.initialize = ({ context }) => {
  return {
    owner({ key }) {
      const url = 'http://localhost:6001/api/.../' + key
      return fetch(url, { headers: { requestId: context.requestId }})
        .then(response => {
          return response.json()
        })
        .then(json => {
          return transform(json)
        })
        .catch(err => {
          console.trace(err)
        });
    }
  }
};

除了更好的代码组织之外,这样做还可以简化测试,因为您的解析器不需要任何外部依赖关系。您可以通过向上下文预加载所需的任何测试内容来以这种方式注入依赖关系,并且可以处理业务逻辑所属的业务逻辑。

使用请求的上下文初始化业务逻辑还使您可以根据请求调整功能:requestId(如我所示),访问控制等。

答案 1 :(得分:0)

语法() => {}只是一个函数定义。 resolve字段需要一个函数定义,以便在必须解析该字段时可以运行它。
您可以将解析功能移至其他文件,如下所示:
car-data-resolve.js

const resolveCarData = (obj, args) => {
  const url = 'http://localhost:6001/api/.../' + args.key
  return fetch(url)
  .then(response => {
    return response.json()
  })
  .then(json => {
    return transform(json)
  })
  .catch(err => {
    console.trace(err)
  })  
}
export default resolveCarData;

然后在您的架构定义中使用它:

import resolveCarData from './car-data-resolve';

const RootQueryType = new GraphQLObjectType({
    name: 'RootQueryType',

    fields: {
        /* Other fields */
        carData: {
            type: carType,
            description: 'Get owned vehicles',
            args: { key: { type: GraphQLString } },
            resolve: resolveCarData
        },
    },
});