Node使用Graphql

Node使用Graphql

我们在实际的开发过程中同城会出现这种情况,单个后台对应多个前端,而且前端需要的数据格式并不一样,这就需要后端进行判断或者使用中台进行数据处理

中台的搭建有两种方法

  • 使用axios.all方法获取数据进行处理。
exports.get = ({url, params={}}) => {
  return axios({
    url,
    params
  })
  .then((result) => {
    return result.data
  })
}

exports.all = (promiseArr) => {
  return axios.all(promiseArr)
    .then(axios.spread((...resultList) => {
      return resultList
    }))
}
router.get('/all', async (req, res, next) => {
  let java = await get({
    url: 'http://localhost:9000/api/list'
  })

  let node = get({
    url: 'http://localhost:4040/users'
  })

  let php = get({
    url: 'https://ik9hkddr.qcloud.la/index.php/trade/get_list'
  })

  let nodeAndphp = await all([node, php])
  
  res.json({
    java,
    nodeAndphp
  })
})

此方法会返回一个新的数据类型格式,但只是对数据进行简单的拼接,笼统的返回,并不能进行太多的处理,所以引出第二种方法。

  • Graphql

我们这里主要分为两个方面,对于node比较流行的框架来说,其实网上对于express的搭建方法有很多,但是对于koa的就比较少了

  • express

  • koa2

express

npm install express express-graphql graphql

const express = require('express')
const graphqlHTTP = require('express-graphql')
const app = express()
// 配置路由
app.use('/graphql', graphqlHTTP(req => {
  return {
    schema: yourSchema,
    graphiql: true // 是否开启可视化工具
    //当然这里的参数肯定不止这两个  可以通过访问官网查询
  }
}))
// 服务使用3000端口
app.listen(3000);

express-graphql传送门

Koa2

这里有两种方式去实现:

const Koa = require('koa')
const graphqlHTTP = require('koa-graphql');
const Router = require('koa-router');
const app = new Koa()
const router = new Router();
const schema = require('./schema')

router.all('/graphql', graphqlHTTP({
  schema: schema,
  graphiql: {
    editorTheme: 'blackboard'
  }
}));

app.use(router.routes()).use(router.allowedMethods());
app.listen(4000)
const Koa = require('koa');
const mount = require('koa-mount');
const graphqlHTTP = require('koa-graphql');
const schema = require('./schema')
const app = new Koa();
 
app.use(mount('/graphql', graphqlHTTP({
  schema:schema,
  graphiql: true
})));
 
app.listen(4000);

Schema

每一个GraphQL服务都会定义一套类型,来描述服务可能返回的所有数据。当执行一个查询时,服务会根据定义的Schema验证并执行查询。

//标量类型
GraphQLInt
GraphQLString
GraphQLBoolean
GraphQLID //其实这个我没懂他和int有什么区别。。
//我简单的理解为这些类似于js的基本类型

除此之外,schema还有 定义(Definitions) 常用的定义如下

  • GraphQLObjectType
var AddressType = new GraphQLObjectType({
  name: 'Address',
  fields: {
    street: { type: GraphQLString },
    number: { type: GraphQLInt },
    formatted: {
      type: GraphQLString,
      resolve(obj) {
        return obj.number + ' ' + obj.street
      }
    }
  }
});

var PersonType = new GraphQLObjectType({
  name: 'Person',
  fields: () => ({
    name: { type: GraphQLString },
    bestFriend: { type: PersonType },
  })
});
  • GraphQLInterfaceType

当一个字段可能返回多种不同类型时,可使用接口类型 GraphQLInterfaceType,来描述所有可能类型必须有的共同字段,也可指定 resolveType 函数来决定该字段实际被解析时为何种类型。

const AnimalType = new GraphQLInterfaceType({
    name: 'Animal',
    description: 'Animal接口',
    fields: {
      species: {
        type: GraphQLString,
        description: '动物物种',
      }
    },
})
  
const dogType = new GraphQLObjectType({
    name: 'dog',
    interfaces: [AnimalType],
    description: 'dog数据',
    fields: {
      species: {
        type: GraphQLString,
        description: '动物物种'
      },
      name: {
        type: GraphQLString,
        description: '名称'
      }
    },
    isTypeOf: (obj) => {
        return obj.name
    }
})
  
const fishType = new GraphQLObjectType({
    name: 'fish',
    interfaces: [AnimalType],
    description: 'fish数据',
    fields: {
      species: {
        type: GraphQLString,
        description: '动物物种'
      },
      color: {
        type: GraphQLString,
        description: '颜色'
      }
    },
    isTypeOf: (obj) => {
        return obj.color
    }
})
schema = new GraphQLSchema({
    types: [AnimalType, dogType, fishType],
    query:new GraphQLObjectType({
        name:"schema",
        fields:{
            fetchInterfaceData:{
                type: new GraphQLList(AnimalType),
                description: 'interface类型数据例子',
                resolve: (root, params, context) => {
                return [
                        {
                            "species": "哈士奇",
                            "name": "旺财"
                        },
                        {
                            "species": "热带鱼",
                            "color": "红色"
                        }
                    ]
                },
            }
        }
    }),
})
//查询:
query fetchInterfaceData {
   fetchInterfaceData {
     species
     ...on dog{
       name
     }
     ...on fish{
       color
     }
   }
}
//输出
{
  "data": {
    "fetchInterfaceData": [
      {
        "species": "哈士奇",
        "name": "旺财"
      },
      {
        "species": "热带鱼",
        "color": "红色"
      }
    ]
  }
}
  • GraphQLUnionType

当一个字段可以返回多种不同类型时,可使用联合类型 GraphQLUnionType 描述所有可能类型,也可指定 resolveType 函数来决定该字段实际被解析时为何种类型。

const {
    GraphQLString,
    GraphQLList,
    GraphQLUnionType,
    GraphQLObjectType
} = require('graphql')

const weixinType = new GraphQLObjectType({
    name: 'weixinItem',
    description: 'weixin数据',
    fields: {
        source: {
            type: GraphQLString,
            description: '来源'
        },
        title: {
            type: GraphQLString,
            description: '标题'
        }
    }
})

const weiboType = new GraphQLObjectType({
    name: 'weiboItem',
    description: 'weibo数据',
    fields: {
        source: {
            type: GraphQLString,
            description: '来源'
        },
        author: {
            type: GraphQLString,
            description: '作者'
        }
    }
})

const articleUnion = new GraphQLUnionType({
    name: 'articleUnion',
    description: '文章联合类型',
    types: [weixinType, weiboType],
    resolveType: (value) => {
        switch (value.source) {
            case 'weixin':
                return weixinType
            case 'weibo':
                return weiboType
        }
    }
})

schema = new GraphQLSchema({
    query:new GraphQLObjectType({
        name:"schema",
        fields:{
            fetchUnionData:{
                type: new GraphQLList(articleUnion),
                description: 'union类型数据例子',
                resolve: (root, params, context) => {
                    return [
                        {
                            "source": "weixin",
                            "title": "标题 1",
                        },
                        {
                            "source": "weibo",
                            "author": "作者 1"
                        }
                    ]
                }
            }
        }
    }),
})

// 调用例子
query fetchUnionData {
   fetchUnionData {
     ...on weiboItem {
       source
       author
     }
     ...on weixinItem {
      source
       title
     }
   }
}
//结果
{
   "data": {
     "fetchUnionData": [
       {
         "source": "weixin",
         "title": "标题 1"
       },
       {
         "source": "weibo",
         "author": "作者 1"
       }
     ]
   }
}

  • GraphQLEnumType

枚举类型 定义一些有效值的合集

const {
    GraphQLString,
    GraphQLEnumType
} = require('graphql')

const sourceEnumType = new GraphQLEnumType({
    name: 'sourceEnum',
    description: '文章来源枚举类型',
    values: {
        weixin: {
            value: 'weixin',
            description: '微信'
        },
        weibo: {
            value: 'weibo',
            description: '微博'
        }
    }
})
schema = new GraphQLSchema({
    query:new GraphQLObjectType({
        name:"schema",
        fields:{
            fetchEnumData:{
                type: GraphQLString,
                description: 'enum类型数据例子',
                args: {
                    source: {
                        type: sourceEnumType,
                        description: '文章来源类型',
                        defaultValue: 'weixin'
                    }
                },
                resolve: (root, params, context) => {
                    let { source } = params
                    return source
                }
            }
        }
    }),
})

// 调用例子
query fetchEnumData {
   fetchEnumData(
    source: weixin
   )
}
//输出
{
  "data": {
       "fetchUnionData": [
         {
           "source": "weixin",
           "title": "标题 1"
         },
         {
           "source": "weibo",
           "author": "作者 1"
         }
       ]
     }
}
  • GraphQLInputObjectType

GraphQL 中的输入对象类型,表示一系列结构化的输入参数。作用于args

const {
    GraphQLInt,
    GraphQLString,
    GraphQLBoolean,
    GraphQLNonNull,
    GraphQLInputObjectType,
} = require('graphql')

const fileObject = new GraphQLInputObjectType({
    name: 'fileObject',
    description: "文件数据",
    fields: () => ({
        type: {
            type: new GraphQLNonNull(GraphQLString),
            description: '文件类型'
        },
        name: {
            type: new GraphQLNonNull(GraphQLString),
            description: '文件的原始文件名称'
        },
        size: {
            type: new GraphQLNonNull(GraphQLInt),
            description: '文件大小(bytes)'
        },
        path: {
            type: new GraphQLNonNull(GraphQLString),
            description: '文件上传后的路径'
        },
    }),
});

let schema = new GraphQLSchema({
    query: new GraphQLObjectType({
        name:'object',
        fields: {
          fetchInputObjectData:{
            type: GraphQLBoolean,
            description: 'inputObject类型数据例子',
            args: {
                file: {
                    type: fileObject,
                    description: 'object类型参数'
                }
            },
            resolve: (root, params, context) => {
                return true
            }
          }
        }
    })
})

//输入
query fetchInputObjectData {
 	fetchInputObjectData(
  file: {
       type: "hello.jpg",
       name: "hello",
     	 size: 1024,
       path: "/img/hello.jpg"
     }
   )
}
//输出
{
  "data": {
    "fetchInputObjectData": true
  }
}
  • GraphQLList

数组类型趴

let Movie = new GraphQLObjectType({
    name:'Movie',
    description:'电影信息',
    fields:{
        id:{
            type:GraphQLInt
        },
        title:{
            type:GraphQLString
        },
        genres:{
            type:GraphQLString
        },
        rating:{
            type:GraphQLFloat
        },
    }
})
let schema = new GraphQLSchema({
    query: new GraphQLObjectType({
        name:'object',
        fields: {
            movies:{
                type:new GraphQLList(Movie),
                resolve(parentValue, args, request){
                   return [
                       {
                        "id": 1,
                        "title": "欧洲攻略",
                        "genres": "喜剧,动作,爱情",
                        "rating": 3.8,
                        "theater": 1
                        },
                        {
                        "id": 2,
                        "title": "精灵旅社3:疯狂假期",
                        "genres": "喜剧,动画,奇幻",
                        "rating": 7.2,
                        "theater": 2
                        },
                   ]
                }
            },
        },
    }),
//查询
query Movie {
  movies{
    id
    title
    genres
    rating
  }
}
//数据
{
  "data": {
    "movies": [
      {
        "id": 1,
        "title": "欧洲攻略",
        "genres": "喜剧,动作,爱情",
        "rating": 3.8
      },
      {
        "id": 2,
        "title": "精灵旅社3:疯狂假期",
        "genres": "喜剧,动画,奇幻",
        "rating": 7.2
      },
    ]
  }
}
  • GraphQLNonNull

字段不能为空

let schema = new GraphQLSchema({
    types: [AnimalType, dogType, fishType],
    query: new GraphQLObjectType({
        name:'object',
        fields: {
            hello: {
                type: new GraphQLNonNull(GraphQLString),
                args: {
                    name: {  // 这里定义参数,包括参数类型和默认值
                        type: GraphQLString,
                        defaultValue: 'Brian'
                    }
                },
                resolve(parentValue, args, request) { // 这里演示如何获取参数,以及处理
                    return 'hello world ' + args.name + '!';
                }
            },
        },
    }),
})
//查询
query hello{
  hello
}
//数据
{
  "data": {
    "hello": "hello world Brian!"
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值