GraphQL 到底怎么用?看看这个例子就知道了

栏目: 前端 · 发布时间: 5年前

内容简介:GraphQL 究竟是什么东西?它实际上是一种 API 查询语言。GraphQL 显示了服务器可以提供的不同类型的数据,然后客户端就可以明确选择它们想要哪些内容。

GraphQL 究竟是什么东西?

它实际上是一种 API 查询语言。

GraphQL 显示了服务器可以提供的不同类型的数据,然后客户端就可以明确选择它们想要哪些内容。

在使用 GraphQL 时,你可以在一个调用中获取多个服务器的资源,而不是像 REST API 那样需要调用多个 API。

理论说得再多也没用,例子才是最直观的。所以,让我们开始使用 GraphQL 吧。

我们将在本文中使用 GraphQL 和 NodeJS。

先决条件

下载和安装 NodeJS: https://nodejs.org/en/

如何在 NodeJS 中使用 GraphQL

GraphQL 可以与多种语言一起使用。在这里,我们将重点介绍如何在 NodeJS 中使用 GraphQL。

创建一个叫作 graphql-with-nodejs 的文件夹。进入这个文件夹,并运行 npm init 来创建 NodeJS 项目。

复制代码

cd graphql-with-nodejs
npminit

安装依赖项

使用以下命令安装 Express。

复制代码

npminstallexpress

使用以下命令安装 GraphQL。我们将安装 graphql 和 express-graphql。

复制代码

npminstallexpress-graphql graphql

NodeJS 代码

在项目中创建一个叫作 server.js 的文件,并将下面的代码复制到文件中。

复制代码

constexpress =require('express');
constport =5000;
constapp = express();

app.get('/hello',(req,res) =>{
    res.send("hello");
   }
);

app.listen(port);
console.log(`Server Running at localhost:${port}`);

上面的代码提供了一个叫作 /hello 的 HTTP 端点。

这个端点是使用 express 创建的。

现在让我们修改代码,启用 GraphQL。

修改代码,启用 GraphQL

GraphQL 将提供一个叫作 /graphql 的端点,负责处理所有的请求。

将下面的代码复制到 server.js 文件中。

复制代码

//get all the libraries needed
constexpress =require('express');
constgraphqlHTTP =require('express-graphql');
const{GraphQLSchema} =require('graphql');

const{queryType} =require('./query.js');

//setting up the port number and express app
constport =5000;
constapp = express();

 // Define the Schema
constschema =newGraphQLSchema({query: queryType });

//Setup the nodejs GraphQL server
app.use('/graphql', graphqlHTTP({
   schema: schema,
   graphiql:true,
}));

app.listen(port);
console.log(`GraphQL Server Running at localhost:${port}`);

我们在 /graphql 端点上建立了一个 GraphQL 服务器,它知道如何处理收到的请求。

GraphQL 服务器是通过下面的代码建立起来的。

复制代码

app.use('/graphql', graphqlHTTP({
   schema: schema,
   graphiql: true,
}));

现在让我们来看一下 graphqlHTTP 的参数。

graphiql

graphiql 是一个 Web UI,你可以用它来测试 graphql 端点。我们将其设置为 true,这样就可以很容易测试我们创建的各种 graphql 端点。

schema

虽然 graphql 只提供了一个外部端点 /graphql,但它可以拥有多个其他端点,用于执行其他各种操作。这些端点可以在 schema 中指定。

schema 将执行以下操作:

  • 指定端点;

  • 指定端点的输入和输出字段;

  • 指定在端点被调用时应该执行哪些操作,等等。

schema 的定义如下。

复制代码

const schema =newGraphQLSchema({query:queryType});

schema 可以包含查询和可变类型,不过本文只关注查询类型。

query

在这个定义中可以看到,query 已被设置为 queryType。

我们使用以下命令从 query.js 文件导入 queryType。

复制代码

const{queryType} =require('./query.js');

query.js 是一个自定义文件,我们稍后会创建它。

在项目中创建一个叫作 query.js 的文件,并将下面的代码复制到文件中。

复制代码

const{ GraphQLObjectType,
    GraphQLString
} =require('graphql');

//Define the Query
constqueryType =newGraphQLObjectType({
   name:'Query',
   fields: {
       hello: {
           type: GraphQLString,

           resolve:function(){
               return"Hello World";
            }
        }
    }
});

exports.queryType = queryType;

有关这个 query 的说明

queryType 是一个 GraphQLObjectType 对象,并指定了名称 Query。

我们在 fields 中指定各种端点,我们在这里添加一个叫作 hello 的端点。

hello 的 type 是 GraphQLString,这意味着这个端点的返回类型为字符串。因为这是 graphql schema,所以字符串类型是 GraphQLString 而不是 String。如果直接使用 String 是不行的。

resolve 函数在调用端点时会被执行。这里的操作是返回字符串“Hello World”。

最后,我们使用 exports.queryType = queryType 导出 queryType。这样我们就可以在 server.js 中导入它。

运行应用程序

使用以下命令运行这个应用程序。

复制代码

nodeserver.js

应用程序将运行在 localhost:5000/graphql 上。

你可以通过访问 localhost:5000/graphql 来测试应用程序。

Graphiql Web UI 如下图所示。

GraphQL 到底怎么用?看看这个例子就知道了

左侧是输入,右侧是输出。

给定以下输入:

复制代码

{
  hello
}

将给出以下输出:

复制代码

{
 "data": {
   "hello":"Hello World"
  }
}

添加更多端点

我们将创建 2 个新端点:

  • movie:根据给定的电影 ID 返回一部电影的信息。

  • director:根据给定的导演 ID 返回导演的信息,它还将返回该导演指导的所有电影信息。

添加数据

通常,应用程序将从数据库中读取数据。但在本文中,我们只是简单地在代码中硬编码一些数据。

创建一个叫作 data.js 的文件并添加以下代码。

复制代码

//Hardcode some data for movies and directors
let movies = [{
    id:1,
    name:"Movie 1",
    year:2018,
    directorId:1
},
{
    id:2,
    name:"Movie 2",
    year:2017,
    directorId:1
},
{
    id:3,
    name:"Movie 3",
    year:2016,
    directorId:3
}
];

let directors = [{
    id:1,
    name:"Director 1",
    age:20
},
{
    id:2,
    name:"Director 2",
    age:30
},
{
    id:3,
    name:"Director 3",
    age:40
}
];

exports.movies = movies;
exports.directors = directors;

这个文件包含电影和导演的数据。我们将使用这个文件中的数据作为端点的数据来源。

将 movie 端点添加到 query 中

新端点将被添加到 query.js 文件的 queryType 中。

复制代码

movie: {
           type: movieType,
           args: {
               id:{ type: GraphQLInt }
            },
           resolve:function(source, args){
               return_.find(movies, {id:args.id});
            }
        }

这个端点的返回类型是 movieType,我们会在后面定义它。

args 参数用于指定 movie 端点的输入。这个端点的输入是 id,类型是 GraphQLInt。

resolve 函数将从电影列表中返回与 id 对应的电影。find 是一个来自 lodash 库的函数,用于查找列表中的元素。

query.js 的完整代码如下所示。

复制代码

const{ GraphQLObjectType,
    GraphQLString,
    GraphQLInt
} =require('graphql');
const_ =require('lodash');

const{movieType} =require('./types.js');
let{movies} =require('./data.js');

//Define the Query
constqueryType =newGraphQLObjectType({
   name:'Query',
   fields: {
       hello: {
           type: GraphQLString,
           resolve:function(){
               return"Hello World";
            }
        },

       movie: {
           type: movieType,
           args: {
               id:{ type: GraphQLInt }
            },
           resolve:function(source, args){
               return_.find(movies, {id:args.id});
            }
        }
    }
});

exports.queryType = queryType;

从上面的代码可以看出,movieType 实际上是在 types.js 中定义的。

添加自定义类型 movieType

创建一个叫作 types.js 的文件,将下面的代码添加到 types.js 文件中。

复制代码

const {
   GraphQLObjectType,
   GraphQLID,
   GraphQLString,
   GraphQLInt
} = require('graphql');

// Define Movie Type
movieType =newGraphQLObjectType({
    name:'Movie',
    fields: {
        id: {type:GraphQLID},
        name: {type:GraphQLString},
        year: {type:GraphQLInt},
        directorId: {type:GraphQLID}
    }
});

exports.movieType = movieType;

可以看出,movieType 是一个 GraphQLObjectType 对象。

它有 4 个字段 id、name、year 和 directorId。在添加这些字段时同时也指定每个字段的类型。

这些字段直接来自之前定义的数据,也就是电影列表。

为 director 端点添加查询和类型

与 movie 端点类似,我们也可以添加 director 端点。

复制代码

director: {
           type: directorType,
           args: {
               id:{ type: GraphQLInt }
            },
           resolve:function(source, args){
               return_.find(directors, {id:args.id});
            }
        }

在 types.js 中添加 directorType。

复制代码

//Define Director Type
directorType =newGraphQLObjectType({
    name:'Director',
    fields: {
        id: {type:GraphQLID},
        name: {type:GraphQLString},
        age: {type:GraphQLInt},
        movies: {
           type:newGraphQLList(movieType),
            resolve(source, args) {
               return_.filter(movies, { directorId: source.id });
            }
        }
    }
});

directorType 与 movieType 略有不同,为什么会这样?

为什么 directorType 中会有一个 resolve 函数?之前我们只在 query 中看到过这个函数。

directorType 的不同之处

当 director 端点被调用时,我们必须返回导演以及导演所指导的所有电影的信息。

directorType 中的前 3 个字段 id、name、age 直接来自之前定义的数据(导演列表)。

第四个字段 movies 需要包含这位导演所指导的电影列表。

为此,movies 字段的类型是 GraphQLList。

但究竟如何才能找到这位导演指导的所有电影?

为此,我们在 movies 字段中指定了 resolve 函数。这个函数的输入是 source 和 args。

source 将持有父对象的详细信息。

假设某个导演的字段 id = 1、name = “Random”、age = 20, 那么 source.id = 1

source.name = “Random”、source.age = 20。

因此,在这个示例中,resolve 函数将找出 directorId 与给定导演 ID 相匹配的所有影片。

代码

这个应用程序的完整代码可以在 GitHub( https://github.com/aditya-sridhar/graphql-with-nodejs )上找到。

测试应用程序

现在让我们根据不同的场景来测试这个应用程序。

使用 node server.js 运行应用程序.

访问 localhost:5000/graphql,尝试以下输入。

movie

输入:

复制代码

{
  movie(id:1) {
    name
  }
}

输出:

复制代码

{
 "data": {
   "movie": {
     "name":"Movie 1"
    }
  }
}

从上面可以看出,客户端可以明确地请求它想要的东西,GraphQL 确保只返回需要的参数。这里只请求 name 字段,所以服务器只返回这个字段的内容。

在 movie(id: 1) 中,id 是输入参数。我们要求服务器发回 id 为 1 的电影。

输入:

复制代码

{
  movie(id:3) {
   name
   id
   year
  }
}

输出:

复制代码

{
 "data": {
   "movie": {
     "name":"Movie 3",
     "id":"3",
     "year":2016
    }
  }
}

在上面的示例中,请求了 name、id 和 year 字段,所以服务器返回所有这些字段。

director

输入:

复制代码

{
  director(id:1) {
    name
    id,
    age
  }
}

输出:

复制代码

{
 "data": {
   "director": {
     "name":"Director 1",
     "id":"1",
     "age":20
    }
  }
}

输入:

复制代码

{
  director(id:1) {
   name
   id,
    age,
    movies{
     name,
     year
    }
  }
}

输出:

复制代码

{
 "data": {
   "director": {
     "name":"Director 1",
     "id":"1",
     "age":20,
     "movies": [
        {
         "name":"Movie 1",
         "year":2018
        },
        {
         "name":"Movie 2",
         "year":2017
        }
      ]
    }
  }
}

英文原文: https://dev.to/adityasridhar/what-is-graphql-and-how-to-use-it-1f58


以上所述就是小编给大家介绍的《GraphQL 到底怎么用?看看这个例子就知道了》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数学与泛型编程

数学与泛型编程

[美]亚历山大 A. 斯捷潘诺夫(Alexander A. Stepanov)、[美]丹尼尔 E. 罗斯(Daniel E. Rose) / 爱飞翔 / 机械工业出版社 / 2017-8 / 79

这是一本内容丰富而又通俗易懂的书籍,由优秀的软件设计师 Alexander A. Stepanov 与其同事 Daniel E. Rose 所撰写。作者在书中解释泛型编程的原则及其所依据的抽象数学概念,以帮助你写出简洁而强大的代码。 只要你对编程相当熟悉,并且擅长逻辑思考,那么就可以顺利阅读本书。Stepanov 与 Rose 会清晰地讲解相关的抽象代数及数论知识。他们首先解释数学家想要解决......一起来看看 《数学与泛型编程》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器