实战经验:使用 GraphQL 构建现代应用程序

在当今互联网时代,越来越多的应用程序采用前后端分离的架构,前端负责渲染页面并与后端进行交互,后端则提供数据接口供前端调用。传统的 RESTful API 虽然使用简单,但是存在一些缺点,比如需要进行多次请求才能获得所需的数据,而且在处理嵌套关系的数据时也不够灵活。而 GraphQL 作为一种新兴的 API 查询语言,正好能够解决这些问题。

什么是 GraphQL?

GraphQL 是一种由 Facebook 开发的 API 查询语言和运行时,其设计理念是将应用程序的数据需求与后端数据提供方面进行解耦。简单来说,GraphQL 可以让前端开发者在查询数据时明确要求所需的数据,由后端提供方返回和客户端需求一致的数据,从而实现前后端数据关系的协调和更好的数据解耦。

GraphQL 的优点

相比于传统的 RESTful API,GraphQL 有以下优点:

  • 更好的性能:GraphQL 可以一次性请求所需的所有数据,减少了 HTTP 请求次数,提高了应用程序的性能。
  • 更好的灵活性:GraphQL 允许前端开发者在查询数据时明确需要的数据,并返回与需求一致的数据,从而降低了后端开发者的工作量。同时,由于 GraphQL 可以使用任何数据源(例如关系型数据库、非关系型数据,甚至 Web API)作为后台数据提供方,因此可以更好地适应企业应用程序的需求。
  • 更好的嵌套查询性能:GraphQL 允许在查询时嵌套请求,从而减少数据处理的往返和数据格式转换的时间,提高了查询速度和灵活性。

如何使用 GraphQL?

1. 安装 GraphQL

使用 GraphQL 需要安装并配置相应的运行环境。在 Node.js 中,可以通过 NPM 包管理器安装 GraphQL。首先需要在命令行中使用以下命令初始化 Node.js 项目:

--- ---- --

接着安装 GraphQL 并相应的依赖项:

--- ------- ------- ------- ---------------

其中,express 是 Node.js 的 Web 服务器框架,express-graphql 是配合 express 使用的 GraphQL 中间件。使用 npm ,无需为 GraphQL 应用程序配置自己的数据库,我们将会使用 JSONPlaceholder API 公共测试 API 来取代数据库,以进行演示。

接下来,在 app.js 文件中设置服务器:

----- ------- - -------------------
----- -------------- - ---------------------------
----- - ----------- - - -------------------

-- -- ------- ------
----- ------ - -------------
  ---- ----- -
    -------- ------
  -
---

-- -- ------- --------
----- -------- - -
  -------- -- -- ------- --------
--

-- -----
----- --- - ----------
--------
  -----------
  ----------------
    ------- -------
    ---------- ---------
    --------- -----
  --
--

-- -----
---------------- -- -- -
  -------------------- ------ -- -------------
---

运行以上代码,然后打开浏览器用地址栏访问 http://localhost:4000/graphql; 将会看到 GraphQL Playground,如下图所示:

2. 定义 GraphQL Schema

首先需要定义一个 GraphQL Schema,它是一种定义数据类型和查询类型的 GraphQL API 描述语言,类似于数据库中的架构。在定义 Schema 之前,首先需要了解一下 GraphQL 数据类型。

  • 标量类型:GraphQL 中的标量类型指非嵌套数据类型,包括 Int、Float、String、Boolean 和 ID。这些类型的值可以直接作为响应数据。
  • 列表类型:表示允许返回多个值的数据类型,在 Schema 中是用中括号表示的。
  • 对象类型:表示允许返回一组相关数据类型的数据类型,在 Schema 中是用 {} 表示的。

在创建 Schema 时,需要使用 buildSchema 函数。在 Schema 中,可以定义一个或多个类型,每个类型包含一个或多个字段。使用 type 关键字定义类型,字段可以包含标量类型、列表类型和对象类型。

这里,我们来定义一个 Todo 类型,并定义其包含的字段:

----- ------ - -------------
  ---- ---- -
    --- ----
    ------ -------
    ---------- --------
  -

  ---- ----- -
    --------- ------
  -
---

上述代码定义了一个名为 Todo 的类型和一个名为 Query 的类型。在 Todo 类型中,定义了三个字段:id(Int 类型)、title(String 类型)和 completed(Boolean 类型),其中 id 和 title 字段是必需的,由于它们后面带有感叹号,也就是定义了 GraphQL 中的标量类型的非空类型。在 Query 类型中,定义了一个名为 getTodos 的字段,其类型为 [Todo],这表示返回一个 Todo 类型的列表。

3. 定义 GraphQL Resolver

定义 Schema 后,需要定义 Resolver 函数来完成查询逻辑。Resolver 函数是将前端请求转换为 API 响应的中间件。在 Resolver 函数中,可以编写任何代码,用于返回处理后的数据。Resolver 函数与 GraphQL 中定义的每个字段对应,用于对前端请求进行处理,并返回相应的数据。

对于上述定义的 Todo 类型及其所对应的 getTodos 字段,可以这样进行 Resolver 处理:

----- -------- - -
  --------- ----- -- -- -
    ----- -------- - ----- ------
      --------------------------------------------
    --
    ----- ----- - ----- ----------------
    ------ -------------- ----
  --
--

在 Resolver 中,使用 ES6 异步函数获取公共测试 API 中的前 10 条待办事项,将其返回给前端。如果发送请求到服务端,将会得到如下数据:

-
  ------- -
    ----------- -
      -
        ----- --
        -------- --------- --- -------
        ------------ -----
      --
      -
        ----- --
        -------- ----- -- --- ------- -- ------- -----
        ------------ -----
      --
      -
        ----- --
        -------- ------- ------ -------
        ------------ -----
      --
      -- ---
    -
  -
-

4. 进行查询

对于上述的 getTodos 查询,可以使用 GraphQL 查询语言进行查询。在 Playground 工具的左侧窗格中,可以输入查询和变量。在此之前,我们需要先了解一下 GraphQL 的查询语言。

查询语言

在查询中,需要指定所需的数据。最简单的查询语言是 query { fieldName }

例如,我们的 getTodos 查询可以像这样进行查询:

----- -
  -------- -
    --
    -----
  -
-

上述查询中,我们要求获取 Todo 类型的所有 id 和 title 字段。发送查询后,服务器响应应该与上面提到的相同。将获取到以下数据:

-
  ------- -
    ----------- -
      -
        ----- --
        -------- --------- --- ------
      --
      -
        ----- --
        -------- ----- -- --- ------- -- ------- ----
      --
      -
        ----- --
        -------- ------- ------ ------
      --
      -- ---
    -
  -
-

查询参数

GraphQL 支持在查询中传递参数,可以根据参数来过滤查询结果。

例如,以下是一个名为 getTodo 的查询,并接受一个参数(id),返回指定 ID 的待办事项:

----- ---------------- ----- -
  --------------- ---- -
    --
    -----
    ---------
  -
-

上述查询中,我们使用 query 关键字定义了一个名为 GetTodoByID 的查询。使用 $ 单词来定义一个名为 id 的变量并指定类型。例如,在 Playground 窗口中输入变量如下:

-
  ----- -
-

然后运行查询时,我们将传递变量给查询。查询语言将解析由 $ 开头的变量名,然后将参数替换为变量所匹配的值。在上述查询中,参数 id 的类型为 Int,这意味着应该定义一个整数来传递值,这里传递了在查询后面传递的变量值,最后服务端响应结果为:

-
  ------- -
    -------------- -
      ----- --
      -------- ----- -- --- ------- -- ------- -----
      ------------ -----
    -
  -
-

查询示例

假设一个应用程序需要展示一家餐厅的菜单,以及每个菜品对应的价格、种类和选项等。可能会有这样一个数据模型:

-
  ----- -------
  ------ -
    -
      ----- -------
      ------ -
        -
          ----- -------
          ------ ------
          --------- -------
          -------- -
            -
              ----- -------
              ------ -----
            -
          -
        -
      -
    -
  -
-

可以使用 GraphQL 对其进行查询:假设餐厅的名称是“Beauty”,菜单名为“午餐”,我们想要查询出所有菜单项及其相关信息,可以这样写:

----- ------------ -
  ---------------- --------- -
    ----------- ----- -
      ----- -
        ----
        -----
        --------
        ------- -
          ----
          -----
        -
      -
    -
  -
-

创建/更新/删除操作

GraphQL 也支持进行创建,更新和删除操作,这些操作可以使用 Mutation 操作来完成。Mutation 操作的语法很像查询操作,只是它们不是对现有数据的读取,而是变更现有数据。

例如,在下面的例子中,通过 Mutation 操作可以创建一个新的待办事项:

-------- ---------- -
  ----------------- - ------ ---- ------- --- -- -
    --
    -----
    ---------
  -
-

总结

以上内容仅是 GraphQL 的冰山一角,关于 GraphQL 的复杂功能,比如分页、订阅和错误处理等,需要自行查阅相关文档。但从概念出发,GraphQL 就是一种协商数据协议,允许客户端和服务器之间定义应用程序界面和数据模型的精细映射。它降低了前后端的信息治理成本,并在策略、编码和架构方面带来了新的优势。虽然 GraphQL 并不能使您避免代码编写,但它会使代码更简单。通过与 API 的交互,GraphQL 描述性地重新定义了数据,降低了演进的代价,结果是可以更快地迭代应用程序并提供更好的数据访问控制。

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/6480292a48841e9894fa742f


猜你喜欢

  • 在 Deno 中使用 WebSocket 实现简单的游戏

    WebSocket 是一种实时通信协议,它能够在客户端和服务器之间建立持久的连接,可以让浏览器和服务器实时地进行双向通信。在前端开发中,经常会用到 WebSocket 进行实时通信。

    1 年前
  • 解决 Material Design 中使用 CollapsingToolbarLayout 无法折叠的问题

    在 Material Design 中,CollapsingToolbarLayout 是一个非常重要的组件,它能够实现头部折叠的效果,用于实现一些炫酷的效果。但是,在一些情况下,我们可能会遇到 Co...

    1 年前
  • Koa2 中使用 pm2 部署 Node.js 应用的方法

    前言 在 Node.js 应用的开发中,部署是一个非常重要的环节。Koa2 作为一个轻量级的 Node.js Web 框架,应用广泛,而 pm2 作为 Node.js 的进程管理器也是一个非常流行的工...

    1 年前
  • 如何使用 Cypress 和 Cucumber-js 中的 Gherkin 语言编写端到端测试

    简介 端到端测试(End-to-end testing)是一种测试方式,通过模拟真实场景下用户的交互和操作,验证整个应用系统(前端和后端)的功能是否都正常,以及系统是否符合预期的业务需求和用户需求。

    1 年前
  • CSS Grid 如何实现棋盘布局?

    CSS Grid 是一个能够使我们更轻松地实现网页布局的工具。借助它,我们可以轻松地实现复杂的布局效果,比如栅格布局、圣杯布局等。本文将介绍如何使用 CSS Grid 实现一个常见的布局效果 —— 棋...

    1 年前
  • PM2 进程管理和 Node.js 日志管理

    在开发 Node.js 项目时,进程管理和日志管理是非常重要的一部分。本文将介绍 PM2 进程管理和 Node.js 日志管理的相关知识,并提供示例代码。 什么是 PM2 进程管理? PM2 是一个高...

    1 年前
  • Next.js 的生态圈与组件库介绍

    前言 近年来,Next.js 以其快速的开发速度、可靠的应用性能和广泛的生态圈而备受关注。作为一款轻量级的框架,Next.js 为开发者提供了许多方便的工具和库,让开发者可以轻松地构建出高质量的 We...

    1 年前
  • 如何使用 Headless CMS 实现 RSS 订阅功能

    现如今,RSS 已经成为互联网上非常有用的一种信息订阅方式。它允许用户订阅自己感兴趣的网站,从而第一时间获得最新的文章和更新。如何让你的网站支持 RSS 订阅,这里我们介绍一种方法:使用 Headle...

    1 年前
  • 利用 ES8 中的 Trailing Commas 语法细节,提高代码可读性

    在 JavaScript 的发展历程中,ES8 引入了一种新的语法细节:Trailing Commas。它允许在对象、数组、函数参数等复合结构的尾部添加一个逗号,即使这个逗号后面没有内容。

    1 年前
  • 使用 Mocha 测试和优化 JavaScript 性能

    随着 Web 技术的不断发展,前端开发成为了越来越受欢迎的职业。而前端开发中 JavaScript 使用量也越来越大,如何优化 JavaScript 的性能成为了前端开发的重要课程之一。

    1 年前
  • RESTful API 数据分析及统计方法

    RESTful API 是前端开发非常常用的方法之一,通过这种方法可以方便地获取和处理数据。然而,在使用 RESTful API 进行数据分析时,也存在一些需要注意的问题,本文将会详细讲解 RESTf...

    1 年前
  • React Native 如何实现定位功能

    React Native 是一种十分流行的移动开发框架,它可以同时支持 iOS 和 Android 平台,并提供了丰富的组件库和 API,可以轻松实现各种功能。在移动开发中,定位功能是一项非常重要的功...

    1 年前
  • Mongoose 如何使用 $text 操作符进行文本查询?

    Mongoose 如何使用 $text 操作符进行文本查询? 在使用 MongoDB 进行数据存储的应用中,文本查询是一种十分常见的需求。而 Mongoose 作为一种 MongoDB ODM(Obj...

    1 年前
  • Node.js 中的文本处理技术详解

    Node.js 中的文本处理技术详解 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,它的出现极大地扩展了 JavaScript 的应用范围,尤其是在服务器端和...

    1 年前
  • PWA 开发中如何避免 Service Worker 频繁更新

    引言 在 PWA 开发中,为了缓存更多的静态资源,提高网站的加载速度,我们通常会使用 Service Worker 来处理缓存策略。但是,在 Service Worker 更新时会重新下载缓存的所有文...

    1 年前
  • 使用 Flexbox 实现响应式图片排列布局

    Flexbox 是一种强大且灵活的布局方式,它允许我们更容易地设计、排列和分配空间,特别是在响应式布局方面,它可以实现简单但有效的网格布局。在本篇文章中,我们将了解如何使用 Flexbox 实现响应式...

    1 年前
  • TypeScript 中获取函数运行时间的常用方法

    在前端开发中,我们往往需要评估代码性能,以便优化我们的应用程序并提高用户体验。在 TypeScript 中可以使用不同的方法来获取函数的执行时间,这篇文章将为你介绍其中的一些常用方法。

    1 年前
  • React Native 项目中如何使用 ESLint

    ESLint 是一个广泛使用的 JavaScript 代码检查工具。在 React Native 项目中,通过使用 ESLint 可以确保代码的可读性和可维护性。在本文中,我将为您介绍如何在 Reac...

    1 年前
  • ES9 的 Promise.finally() 方法和 try...catch 的异同

    ES9 的 Promise.finally() 方法和 try...catch 的异同 前言 在前端开发中,我们会经常使用 Promise 和 try...catch 来捕捉和处理异步和同步函数抛出的...

    1 年前
  • 如何使用 Express.js 构建 RESTful API

    什么是 RESTful API? RESTful API 是一种基于 HTTP 协议的轻量级 Web API 设计规范,它是一种描述客户端(如浏览器)和服务器之间的交互方式的设计风格。

    1 年前

相关推荐

    暂无文章