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. UML学习——类之间的关系

    参考:UML图中类之间的关系:依赖,泛化,关联,聚合,组合,实现 空心菱形为聚合关系:部分与整体,部分可有可无.部分可以单独存在(车子和引擎,引擎可以单独存在) 实心菱形为组合关系:部分与整体,但是部 ...

  2. 重建程序员能力(3)-asp.net MVC框架增加Controller

        MVC在微软中提供的框架目前只是发现是asp.net用.另 8年前,我做了个MVC的Windows APP框架如果有兴趣我日后会介绍给大家,欢迎大家关注.MVC的概念网站上有很多,大家去查阅一 ...

  3. Webpack 4教程 - 第六部分 增强开发时体验

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://wanago.io/2018/08/06/webpack-4-course-part ...

  4. Android ListView的基本应用

    ListView可以说是Android原生开发最基本.最重要的控件之一,良好的使用ListView可以让自己的项目得到提高,下面是ListView最简单的应用方式 定义ListViewlist_vie ...

  5. Java递归方法遍历二叉树的代码

    将内容过程中经常用的内容做个记录,如下内容内容是关于Java递归方法遍历二叉树的内容. package com.wzs; public class TestBinaryTree { public st ...

  6. 大整数相乘问题总结以及Java实现

    最近在跟coursera上斯坦福大学的算法专项课,其中开篇提到了两个整数相乘的问题,其中最简单的方法就是模拟我们小学的整数乘法,可想而知这不是比较好的算法,这门课可以说非常棒,带领我们不断探索更优的算 ...

  7. 记一次使用SimpleDateFormat 格式化时间时遇到的问题

    网上的使用方法一大堆,我就不再介绍了,就写一下自己遇到的问题. 先来实现一下获取当前时间: SimpleDateFormat simpleDateFormat =new SimpleDateForma ...

  8. linux如何批量关闭进程

    碰到需要杀掉某一类进程的时候,如何批量杀掉这些进程,使用awk命令是很好的选择. 代码: ps -ef|grep aaa|grep -v grep|awk '{print "kill -9 ...

  9. 浅析C#中new、override、virtual关键字的区别

    Virtual : virtual 关键字用于修饰方法.属性.索引器或事件声明,并使它们可以在派生类中被重写. 默认情况下,方法是非虚拟的.不能重写非虚方法. virtual 修饰符不能与 stati ...

  10. clipboardjs复制到粘贴板

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat=&qu ...