GraphQL
GraphQL
官方描述:
GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。
优点
- 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
  }
}
- 可拓展性
前端自由选择返回 - 不需要额外代码处理冗余字段
 - 提供 schema
schema 可以在运行时被获取到, 类似thrift的idl文件,比较清楚,简单的方法甚至不需要文档。 - 调试比较方便
 
缺点
- 缓存麻烦
https://graphql.cn/learn/caching/
Relay 和 apollo-client 是两个graphql的前端模块,可以帮你在前端缓存数据。 - GraphQL 在前端如何与视图层、状态管理方案结合,目前也只有 React/Relay 这个一个官方方案。
换句话说,如果你不是已经在用 Node + React 这个技术栈,引入 GraphQL 成本略高,风险也不小,这就很大程度上限制了受众。
而且 FB 官方就只有一个 Node.js 的 reference implementation,其他语言都是社区做的。 - 每一个 field 都对数据库直接跑一个 query,会产生大量冗余 query,虽然网络层面的请求数被优化了,但数据库查询可能会成为性能瓶颈。
FB 本身没有这个问题,因为他们内部数据库这一层也是抽象掉的,写 GraphQL 接口的人不需要顾虑 query 优化的问题。
如何解决?
DataLoader, DataLoader 的主要功能是 batching & caching,帮你合并请求。 - 需要服务端的全力配合
 - 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的更多相关文章
- Facebook的Web开发三板斧:React.js、Relay和GraphQL
		
2015-02-26 孙镜涛 InfoQ Eric Florenzano最近在自己的博客上发表了一篇题为<Facebook教我们如何构建网站>的文章,他认为软件开发有些时候需要比较大的跨 ...
 - facebook graphql
		
思想先进,前端直接从后台调用所需要的数据. 最简单的理解: 从"select * from 学生表" 进化为"select name, sex from 学生表" ...
 - Graphql介绍(Introduction to GraphQL)
		
Introduction to GraphQL GraphQL介绍 Learn about GraphQL, how it works, and how to use it in this seri ...
 - graphql 新API 开发方式
		
我们知道 GraphQL 使用 Schema 来描述数据,并通过制定和实现 GraphQL 规范 定义了支持 Schema 查询的 DSQL (Domain Specific Query Langua ...
 - [GraphQL] Use GraphQLNonNull for Required Fields
		
While certain fields in a GraphQL Schema can be optional, there are some fields or arguments that ar ...
 - [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 ...
 - [GraphQL] Write a GraphQL Schema in JavaScript
		
Writing out a GraphQL Schema in the common GraphQL Language can work for simple GraphQL Schemas, but ...
 - [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 ...
 - [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, ...
 - [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 ...
 
随机推荐
- vue2.0 实现全选和全不选
			
实现思路: 1. v-model 一个收集所有input(除全选框外)数组checkModel ,vue会动态将其checked为true的input的value值存入数组checkModel里 2 ...
 - 《PHP制作个人博客》之四:分类添加及前端导航数据用php动态调取
			
大家好,今天我们接着上一节的全栈营销个人博客制作,上一节我们把博客的模板给加载运行起来.今天我们主要讲解后台模板分类的添加,后台导航的添加,及前台导航的动态调用.一个好的博客,导航很重要,导航就像你网 ...
 - web开发布局---传统布局篇
			
1.传统布局 盒状模型结合 display 属性.float 浮动以及 position 定位属性设计的各式传统布局形式. 2.说再多不如动手实践,下面举三个例子 html 部分代码: <sec ...
 - css 椭圆样式
			
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
 - intellij idea 2017和Jprofiler 10的集成 报错问题
			
本来想用Jprofiler来分析一下自己写的Java项目,以提高代码执行效率和自己的编码能力.结果,官网和网上很多帖子都写了点出session->IDE integrations->选择i ...
 - Go 编译原理实现计算器(测试驱动讲解)
			
本文不需要你掌握任何编译原理的知识. 只需要看懂简单的golang语言即可, 完整的代码示例在GIT, 代码是从writing an interpreter in go这本书抽取了简单的部分出来, 如 ...
 - July 12th, 2018. Thursday, Week 28th.
			
People love what other people are passionate about. 人总是会爱上别人倾注热情的事物. From La La Land. This quote has ...
 - zabbix-agent(zabbix-proxy)配置
			
PidFile=/var/run/zabbix/zabbix_agentd.pidLogFile=/var/log/zabbix/zabbix_agentd.logLogFileSize=30Serv ...
 - 影响Linux发展的四位天才黑客
			
影响Linux发展的四位天才黑客 相信大家对 Linux 再熟悉不过了.我们都知道 Linux继承自 Unix,但其实他们上一代还有一个 Multics.从最早的 Multics 发展到最早版本的 L ...
 - 浏览器中 F12 功能的简单介绍
			
chrome浏览器中 F12 功能的简单介绍 由于F12是前端开发人员的利器,所以我自己也在不断摸索中,查看一些博客和资料后,自己总结了一下来帮助自己理解和记忆,也希望能帮到有需要的小伙伴,嘿嘿! 首 ...