GraphQL:准确地获得你所需要的东西,而不是其他东西
让我们来看看两种情况。
- getUser API返回一堆不相关的数据,而你只需要一个电子邮件地址
- 你必须检索4-5个API来建立一个屏幕
这就是 GraphQL 的用处,在这篇文章中,我将演示如何一步步创建 GraphQL 服务器和 Flutter 客户端。
作为一个应用程序的开发者,你可能会想,我为什么要关心服务器呢?难道我不能直接下载 repo 吗?事实上,根据GraphQL的性质,前端工程师很可能会维护和更新服务器端的代码,所以了解基础知识会有帮助。
Apollo GraphQL服务器
package.json
在项目根目录下创建一个package.json文件,这个文件包含项目的配置数据和依赖关系,它看起来像这样。
{
"name": "graphql-server",
"version": "1.0.0",
"main": "app.js",
"scripts": {...},
"dependencies": {
"apollo-datasource-http": "^0.10.0",...
}
}
数据源
在GraphQL中获取数据有几种方式:从REST API中获取,从GraphQL api中获取,从数据库中获取,这些都是通过数据源完成的。这时,你可以减少大量的api调用,并将其合并为一个。假设我们需要一个api调用来获取用户,一个调用来获取项目列表,那么我们就需要创建两个独立的数据源文件。
const userdata = new (class UserAPI extends HTTPDataSource {
constructor() {
const pool = new Pool("http://localhost:8080/");
super(baseURL, {pool})
}
async getUser(userID) {
return this.get(`/company/${userID}`, {});
}})
module.exports = userdata
第二个数据源文件来获取一个项目列表
//second data source file to fetch list of items
const listdata = new (class UserAPI extends HTTPDataSource {
constructor() {
const pool = new Pool("http://localhost:8080/");
super(baseURL, {pool})
}
async getList(itemID) {
return this.get(`/list`, {query: {itemID: itemID}
});
}})
module.exports = listdata
最后,使用一个索引文件将这两个API合并成一个。
const datasources = () => {
return {
userAPI: UserAPI,
listAPI: ListAPI,
}
};
module.exports = datasources;
模式和解析器
现在我们有了合并API的功能,GraphQL的另一个重要特征是准确地查询你所需要的东西,这是用Schema和Resolver处理的。模式是定义数据,而解析器则负责填充数据。
//Schema
const { gql } = require('apollo-server');
const baseSchema = gql`
type Query {_: Boolean}
type Mutation {_: Boolean}
type User {
userID: String!
userName: String!
}`
module.exports = baseSchema;
//Resolver
const userResolvers = {
Query: {user: (id) => {}}};
module.exports = userResolvers;
GraphQL服务器
首先,我们需要安装Apollo服务器。
npm install apollo-server graphql
现在让我们创建一个GraphQL服务器文件 - project/src/app.js。
const { ApolloServer } = require('apollo-server');
const typeDefs = require('./schema');
const resolvers = require('./resolvers');
const datasources = require('./datasources');
const server = new ApolloServer({typeDefs,resolvers,dataSources});
server.listen({port: 8080}, () => {
console.log('Server is running');
});
启程开始
npm install
npm start
目标架构
你要用GraphQL来代替REST吗?可能不是。最好是将GraphQL作为REST API服务前面的一个额外层。通过这种方式,后端团队可以专注于构建核心服务,而前端团队可以以最适合其性能的方式优化服务器响应。

Flutter GraphQL客户端
过渡期的移动应用层包含:表现形式、领域和数据,而通常数据层负责获取、映射和存储数据。有没有更好的方法呢?如果我们可以抛弃数据层呢?有了GraphQL,这是有可能的。

在Flutter中使用GraphQL是相当容易的,不幸的是,在写这篇文章的时候,还没有一个Apollo Flutter库,因此我们将只使用GraphQL库。让我们来看看依赖性。
name: graph_ql
...
dependencies:
graphql_flutter: ^4.0.0-beta
在main()中启动并创建GraphQL服务器
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
ValueNotifier<GraphQLClient> client = ValueNotifier(GraphQLClient(link:HttpLink('http://localhost:8080/graphql')));
return GraphQLProvider(
client: client,
child: MaterialApp(home: UserScreen()));
}
}
创建一个GraphQL方案
final String getItem = """
query {
item(id: "1") {user(id: "2") {name}}
}""";
在一个Widget中使用数据
class ItemScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Query(
options: WatchQueryOptions(document: gql(getItem), fetchPolicy: FetchPolicy.networkOnly),
builder: (QueryResult result, {VoidCallback refetch, FetchMore fetchMore}) {
if (result.data == null) return Text('Error')
if (result.isLoading) return Text('Loading');
return _buildUserWidget(result.data);
})));
}}
🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉