前言
本篇文章可能稍微长了一点,您需要先准备好时间,以免中途要去上厕所什么的,发生中断。
我们一般都是用REST API, 即后端定义好API的数据结构和参数,前端再传参请求获取数据。
比如我们有个获取用户列表的接口:GET
/user/list
, 返回用户id,用户名,创建时间:
[
{
"id": 1,
"name": "jack",
"created_at": "2021-05-10 13:14:15"
},
{
"id": 2,
"name": "tom",
"created_at": "2021-05-07 12:14:05"
}
]
如果业务需求发生了变化,比如接口要返回用户头像时,就需要后端去改代码,增加用户头像的字段:
[
{
"id": 1,
"name": "jack",
"created_at": "2021-05-10 13:14:15",
"avatar": "https://www.avatar.com/01.jpg"
},
{
"id": 2,
"name": "tom",
"created_at": "2021-05-07 12:14:05",
"avatar": "https://www.avatar.com/02.jpg"
}
]
当后面又要添加字段时,又需要后端去改接口的代码。
有时候后端沉迷在思考中,可能不会很快响应,前端就要等着,或者去模拟些假数据来搞,这样不好。
于是有人就说能不能提供一种接口:让前端来指定字段,让前端来做连表查询,让前端来做分页查询呢?答案是当然有的,比如今天介绍的graphql就是其中的一种方式。
关于graphql
grapql的相关资料可以看:https://graphql.cn/learn/
它提供了一套完整的查询语句,只要后端支持graphql,就能立马使用。一定程度上减少了后端的工作,给前端提供了更好的用户体验。
注意,不是说有了grapql,后端就不用写查询代码,可以开心的去摸鱼了。不是的奥,后端不用写REST API的代码了,但要写graphql的语句哦。
不过,有一说一,有的场景下它还是非常适合的,比如你是做saas的,要开放些查询api给客户,用它呢就可以减少很多工作。
我们来一起试试吧
服务端
我们来搞个服务端,这里就node js来做例子,基于koa框架的apollo-server-koa。
先安装下:
npm i apollo-server-koa
npm i graphql
写个app.js,启动它吧:
const Koa = require('koa');
const { ApolloServer, gql } = require('apollo-server-koa');
async function startApolloServer() {
const typeDefs = gql`
type Query {
hello: String,
hot: String
}
`;
// Provide resolver functions for your schema fields
const resolvers = {
Query: {
hello: () => 'Hello world!',
hot: () => 'Very hot!'
},
};
const server = new ApolloServer({ typeDefs, resolvers });
await server.start();
const app = new Koa();
server.applyMiddleware({ app });
await new Promise(resolve => app.listen({ port: 4000 }, resolve));
console.log(`Server ready at http://localhost:4000${server.graphqlPath}`);
return { server, app };
}
startApolloServer();
启动完成后,访问http://localhost:4000/graphql就能看到一个grahql的查询界面了
其他客户端
图形客户端
好比我们的REST API有postman这样的接口调试工具一样(postman后面也会支持graphql),graphql也有很多的图形客户端:
https://blog.bitsrc.io/13-graphql-tools-and-libraries-you-should-know-in-2019-e4b9005f6fc2
我用的是GraphiQL 和 Altair 。
Altair的颜值高一些,安装也简单,直接去官网下载安装包即可。
后端请求
有时候可能需要后端请求graphql接口,聪明的你已经发现了,它也是http请求,只是格式参数和REST API有些不一样。
比如在shell下,我们可以这样:
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ hello }"}' \
http://localhost:4000/graphql
比如在node下,我们可以这样:
fetch('/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({query: "{ hello }"})
})
.then(r => r.json())
.then(data => console.log('data returned:', data));
fetch看起来可能有点啰嗦,那我们可以用现成的库,比如用graphql-request:
import { request, gql } from 'graphql-request'
const query = gql`
{
Movie(title: "Inception") {
releaseDate
actors {
name
}
}
}
`
request('https://api.graph.cool/simple/v1/movies', query).then((data) => console.log(data))
又或者在PHP下,我们可以封装一个方法:
public static function send_query(string $endpoint,
string $query,
array $variables = [],
?string $token = null)
{
$headers = ['Content-Type: application/json'];
if ($token) {
$headers[] = $token;
}
$content = ['query' => $query];
if(!empty($variables)){
$content['variables'] = $variables;
}
$data = file_get_contents($endpoint, false, stream_context_create([
'http' => [
'method' => 'POST',
'header' => $headers,
'content' => json_encode($content),
]
]));
if($data){
$data = json_decode($data,true);
return $data;
}else{
$error = error_get_last();
return $error;
}
}
查询
有了前面的准备工作,我们就可以开始测试了。
先来查个hello吧:
{
hello
}
可以看到会返回一个结果:
{
"data": {
"hello": "Hello world!"
}
}
OK,今天的介绍就到这里了???就这?我REST API完全可以hold住这种hello world的需求呀,要你何用?
OKK,不急,我们明天继续。