GraphQL

官方描述:

GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。

优点

  1. GraphQL可以让我们通过请求控制返回的字段,以此来减少restful api的设计理念带来的请求多次的问题。

    比如我们要获取指定id的文章相关信息,包括标题、作者、发布时间以及前两条评论;同时加载当前用户信息。
// 两趟查询,难以拓展
GET /user/111
GET /article/1001?comment=2
// 一趟查询,易于扩展
{
article (id: 1001){
title,
author,
time,
comments (first: 2)
nickname,
time,
content
}
},
user (id: 111){
nickname,
photo,
sign
}
}
  1. 可拓展性

    前端自由选择返回
  2. 不需要额外代码处理冗余字段
  3. 提供 schema

    schema 可以在运行时被获取到, 类似thrift的idl文件,比较清楚,简单的方法甚至不需要文档。
  4. 调试比较方便

缺点

  1. 缓存麻烦

    https://graphql.cn/learn/caching/

    Relay 和 apollo-client 是两个graphql的前端模块,可以帮你在前端缓存数据。
  2. GraphQL 在前端如何与视图层、状态管理方案结合,目前也只有 React/Relay 这个一个官方方案。

    换句话说,如果你不是已经在用 Node + React 这个技术栈,引入 GraphQL 成本略高,风险也不小,这就很大程度上限制了受众。

    而且 FB 官方就只有一个 Node.js 的 reference implementation,其他语言都是社区做的。
  3. 每一个 field 都对数据库直接跑一个 query,会产生大量冗余 query,虽然网络层面的请求数被优化了,但数据库查询可能会成为性能瓶颈。

    FB 本身没有这个问题,因为他们内部数据库这一层也是抽象掉的,写 GraphQL 接口的人不需要顾虑 query 优化的问题。

    如何解决?

    DataLoader, DataLoader 的主要功能是 batching & caching,帮你合并请求。
  4. 需要服务端的全力配合
  5. GraphQL不存在鉴权方案,需要自行解决

get start

GraphQL为express和koa提供了插件,可以方便的搭建GraphQL服务器。

看下面的代码:

var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql'); // 使用 GraphQL schema language 构建 schema
var schema = buildSchema(`
input MessageInput {
content: String
author: String
} type Message {
id: ID!
content: String
author: String
} type Query {
getMessage(id: ID!): Message
} type Mutation {
createMessage(input: MessageInput): Message
updateMessage(id: ID!, input: MessageInput): Message
}
`); // 如果 Message 拥有复杂字段,我们把它们放在这个对象里面。
class Message {
constructor(id, {content, author}) {
this.id = id;
this.content = content;
this.author = author;
}
} // 映射 username 到 content
var fakeDatabase = {}; var root = {
getMessage: function ({id}) {
if (!fakeDatabase[id]) {
throw new Error('no message exists with id ' + id);
}
return new Message(id, fakeDatabase[id]);
},
createMessage: function ({input}) {
// Create a random id for our "database".
var id = require('crypto').randomBytes(10).toString('hex'); fakeDatabase[id] = input;
return new Message(id, input);
},
updateMessage: function ({id, input}) {
if (!fakeDatabase[id]) {
throw new Error('no message exists with id ' + id);
}
// This replaces all old data, but some apps might want partial update.
fakeDatabase[id] = input;
return new Message(id, input);
},
}; var app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000, () => {
console.log('Running a GraphQL API server at localhost:4000/graphql');
});

我们通过GraphQL提供的语法,建立一个schema,类似typescript的interface。

有多种基本类型:ID, String, Int, []。

Query是查询操作,Mutation是增删改操作。

所以这里,我们提供了一个getMessage的方法,返回Message类型的信息。

Mutation类型这里我们提供了createMessage,和updateMessage两个方法。

定义完schema,还需要定义方法的处理:

定义root对象进行函数处理。

执行node index.js。然后访问localhost:4000/graphql就可以看到相应的调试页面。(前提是graphiql:true)。



这个调试页面还是很方便的。

打开调试页面,先create一个message:



然后查询这个message:

type 为query的时候,可以不写query。

前端请求

var dice = 1;
var sides = 6; var query = `query RollDice($dice: Int!, $sides: Int) {
rollDice(numDice: $dice, numSides: $sides)
}`; fetch('/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({
query,
variables: { dice, sides },
})
})
.then(r => r.json())
.then(data => console.log('data returned:', data));

这是官网给的试例。fetch请求,把query传过去就可以啦,如果请求的是个函数,需要传参variables。如上dice和sides两个参数

连接数据库

这里给个连接mysql的schema和rootValue


var { buildSchema } = require('graphql'); const mysqlCon = require('./mysql'); // 使用 GraphQL schema language 构造一个 schema
let count = 0;
var schema = buildSchema(`
type UserInfo {
id: ID!
name: String
uid: Int
age: Int
sex: String
createdTime: String
updatedTime: String
description: String
}
type Query {
getUsers: [UserInfo]
getUserById(id: ID!): UserInfo
}
type Mutation {
invokeCount: Int
}
`); // root 为每个端点入口 API 提供一个解析器
var root = {
async getUsers() {
count += 1;
let users = await mysqlCon.pifySelect('select * from Tab_User_Info');
console.log(users);
return users;
},
async getUserById({id}) {
let users = await mysqlCon.pifySelect(`select * from Tab_User_Info where id=${id}`)
return users[0];
},
invokeCount() {
return count;
}
}; module.exports = {
root,
schema,
}

mysql.js

const mysql = require('mysql');

const connection = mysql.createConnection({
host: '127.0.0.1',
port: 3306,
user: 'root',
password: '123456',
database: 'Test_User'
}); connection.connect(function(err) {
if (err) {
console.error('error: ' + err.stack);
return;
}
}); Object.defineProperty(connection, 'pifySelect', {
value: function(sql) {
return new Promise((resolve, _)=>{
connection.query(sql, function (error, results) {
if (error) console.log('mysql select err:', error);
resolve(results);
});
})
}
}) module.exports = connection

用docker搞个mysql环境:

docker pull mysql:5.6
docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6

docker exec -it mysql bash进入bash然后初始化一下mysql,插几个数据用来操作。

用koa-graphql或者express-graphql启一个服务,就可以直接访问啦。

使用方

facebook, twitter,github,我们公司(toutiao)部分业务在用。

GraphQL的更多相关文章

  1. Facebook的Web开发三板斧:React.js、Relay和GraphQL

    2015-02-26 孙镜涛  InfoQ Eric Florenzano最近在自己的博客上发表了一篇题为<Facebook教我们如何构建网站>的文章,他认为软件开发有些时候需要比较大的跨 ...

  2. facebook graphql

    思想先进,前端直接从后台调用所需要的数据. 最简单的理解: 从"select * from 学生表" 进化为"select name, sex from 学生表" ...

  3. Graphql介绍(Introduction to GraphQL)

    Introduction to GraphQL  GraphQL介绍 Learn about GraphQL, how it works, and how to use it in this seri ...

  4. graphql 新API 开发方式

    我们知道 GraphQL 使用 Schema 来描述数据,并通过制定和实现 GraphQL 规范 定义了支持 Schema 查询的 DSQL (Domain Specific Query Langua ...

  5. [GraphQL] Use GraphQLNonNull for Required Fields

    While certain fields in a GraphQL Schema can be optional, there are some fields or arguments that ar ...

  6. [GraphQL] Use Arguments in a GraphQL Query

    In GraphQL, every field and nested object is able to take in arguments of varying types in order to ...

  7. [GraphQL] Write a GraphQL Schema in JavaScript

    Writing out a GraphQL Schema in the common GraphQL Language can work for simple GraphQL Schemas, but ...

  8. [GraphQL] Serve a GraphQL Schema as Middleware in Express

    If we have a GraphQL Schema expressed in terms of JavaScript, then we have a convenient package avai ...

  9. [GraphQL] Use GraphQL's List Type for Collections

    In order to handle collections of items in a GraphQL Schema, GraphQL has a List Type. In this video, ...

  10. [GraphQL] Use GraphQL's Object Type for Basic Types

    We can create the most basic components of our GraphQL Schema using GraphQL's Object Types. These ty ...

随机推荐

  1. js调用百度地图接口绘制任意多边形并获取每个点的经纬度等

    来自:https://blog.csdn.net/u013239236/article/details/52213977 侵删 <!DOCTYPE html> <html> & ...

  2. wordpress 角色权限

    自带多媒体库上传权限:edit_other_pages

  3. arcgis api 3.x for js 入门开发系列十七在线天地图、百度地图、高德地图(附源码下载)

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

  4. Android为TV端助力 转载:RecyclerView分页加载

    package com.android.ryane.pulltoloaddata_recyclerview; import android.os.Handler;import android.os.L ...

  5. 【Linux】【MySQL】CentOS7、MySQL8.0.13 骚操作速查笔记——专治各种忘词水土不服

    1.前言 [Linux][MySQL]CentOS7安装最新版MySQL8.0.13(最新版MySQL从安装到运行) 专治各种忘词,各种水土不服. - -,就是一个健忘贵的速查表:(当然不包括SQL的 ...

  6. ext前后台数据传输的标准化

    一.标准化的数据传输是什么 这里所说的标准化主要是指,使用代理提交数据时,格式必须统一化.标准化,而服务器返回的数据格式也必须是标准化的数据. 简言之,使用代理提交数据时,前台--->后台,后台 ...

  7. sqlserver 2014使用时有Cannot find one or more components

    好久没用sqlserver,今天打开却出现了一个错误,Cannot find one or more components,令人头疼.在启动Microsoft SQL Server Managemen ...

  8. Kubernetes入门-集群安装

    Kubernetes是谷歌开源的容器集群编排平台,是一个完备的分布式系统支撑平台,为容器化应用提供部署运行.资源调度.服务发现和动态伸缩等一系列完整功能,具有强大的故障发现和自我修复机制.服务滚动升级 ...

  9. djangorestframework+vue-cli+axios,为axios添加token作为headers踩坑记

    情况是这样的,项目用的restful规范,后端用的django+djangorestframework,前端用的vue-cli框架+webpack,前端与后端交互用的axios,然后再用户登录之后,a ...

  10. Win7环境 搭建IIS环境。发布asp.net MVC项目到IIS(第一期)

    一.右键添加网站,输入网站基本配置信息. 二.成功添加网站后,应用程序池里会多一个应用,版本一定要改成4.0,并且模式是集成模式,否则项目报错(原因可以看配置文件中的版本信息). 三.再启用项目时可能 ...