资讯专栏INFORMATION COLUMN

GraphQL 的入门指南

马忠志 / 2625人阅读

摘要:允许创建零配置的服务器。这是一种人类可读的模式语法,称为规范与描述语言。类型是表示外观的自定义对象。为此,创建一个名为的新查询。这意味着无论何时在服务器中发生事件,并且每当调用该事件时,服务器都会将相应的数据发送到客户端。

想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!

今天最常讨论的术语之一是 API,很多人不知道 API 到底是什么,API 是 Application Programming Interface(应用程序编程接口)。顾名思义,它是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

你可以将 API 想象成一个酒保。你向酒保要一杯酒,他们会给你想要的。简单,但是传统的 REST API 有什么问题的呢?

自从现代 Web 出现以来,构建 Api 并不像听起来那么困难,但是学习和理解 Api 才是比较难。开发人员是大多数据使用你的 API 来构建某些内容或仅使用数据。所以你的 API 应该尽可能的简洁和直观, 好的 API 是非常容易使用和学习的。直观,在开始设计 API 时常要记住的一点。

我们已经使用 REST 构建 Api 很长时间了。随之而来的也有一些问题,在使用 REST 设计构建 API 时,你会遇到以下问题:

涉及很多端

于开发人员来说,学习和理解你的 API 要困难得多

* 信息的获取有多有少

为了解决这些问题,Facebook 创建了 GraphQL。现在,作者认为 GraphQL 是构建 Api 的最佳方式。这篇文章将告诉你为什么要学习了解一下 GraphQL。

什么是 GraphQL

GraphQL 是 Facebook 开发的一种开源查询语言。它为我们提供了一种更有效的设计、创建和使用 Api的方法。从根本上说,它是 REST 的替代品。

GraphQL有很多特性,比如:

GraphQL查询总是能准确获得你想要的数据,不多不少,所以返回的结果是可预测的, 不再像你使用 REST 那样过度获取信息。

它为我们提供了同一个端,对于同一个 API,没有版本2或版本3。给 GraphQL API 添加字段和类型而无需影响现有查询,老旧字段可以废弃,从工具中隐藏。

GraphQL是强类型的,通过它,可以在执行之前验证 GraphQL 类型系统中的查询, 它帮助我们构建更强大的 Api。

这是对 GraphQL 的基本介绍——为什么它这么强大,为什么它现在这么流行。如果你想了解更多关于它的信息,可以访问 GraphQL网站 学习。

开始

本文的主要目的不是学习如何设置 GraphQL服务器,所以我们现在还没有深入研究。 文本的目标是了解 GraphQL 在实践中的工作原理,因此这里使用简约的零配置 GraphQL 服务器的 Graphpack。

开始项目前,首先我们创建一个新文件名为 graphql-server, 在 mac 终端执行

mkdir graphql-server

接着进入该文件,执行

npm init -y

或者执行

yarn init

npm 将创建一个包 package.json 文件,这个包是你安装的所有依赖项和命令。

现在,我们要安装唯一的依赖项。

Graphpack 允许创建零配置的 GraphQL 服务器。由于刚刚开始使用 GraphQL,这将帮助我们继续学习GraphQL 更多的内容,而不必担心服务器配置,执行以下命令:

npm install --save-dev graphpack

或者使用 yarn 安装:

yarn add --dev graphpack

安装 Graphpack 之后,转到 package.json文件中的脚本,并在其中输入以下代码:

"scripts": {
    "dev": "graphpack",
    "build": "graphpack build"
}

接着创建一个名为 src 的文件夹,它将是整个服务器中唯一的文件夹。

src 文件夹中创建一个名为 schema.graphql 的文件,并写入以下代码:

type Query {
  hello: String
}

schema.graphql 文件将是我们的整个 GraphQL的模式(Schema)。

接着在 src 下创建文件 resolvers.js,并写入以下代码:

import { users } from "./db";

const resolvers = {
  Query: {
    hello: () => "Hello World!"
  }
};

export default resolvers;

这个 resolvers.js 文件是我们提供 GraphQL 操作转换为数据的指令的方式。

接着在 src 下创建一个 db.js 文件并写入以下代码:

export let users = [
  { id: 1, name: "John Doe", email: "john@gmail.com", age: 22 },
  { id: 2, name: "Jane Doe", email: "jane@gmail.com", age: 23 }
];

在本教程中,不使用真实的数据库,所以这个 db.js 文件将模拟一个数据库,只是为了学习的目的。

现在 src 的结构如下:

src
  |--db.js
  |--resolvers.js
  |--schema.graphql

接着运行 npm run dev 或者 yarn dev 启动服务

在浏览器打开 localhost:4000。这里就实现我们在 GraphQL 中的第一个查询,更改和订阅,打开界面如下:

你可以看到 GraphQL Playground,这是一个功能强大的 GraphQL IDE,可用于更好的开发工作流程。 如果你想了解有关 GraphQL Playground的更多信息,请单击此处。

模式(Schema)

GraphQL 有自己的语言类型,用于编写模式。 这是一种人类可读的模式语法,称为规范与描述语言(SDL)。无论使用何种技术,SDL 都是相同的 - 你可以将其用于你想要的任何语言或框架。

这种模式语言非常有用,因为它更直观的看出 API 具有哪些类型,一看到 API 就知道怎么使用。

类型(Type)

类型是 GraphQL 最重要的特性之一。类型是表示 API 外观的自定义对象。例如,如果你正在构建一个社交媒体应用程序,那么你的 API 应该具有诸如文章、用户、赞、组等类型。

类型具有字段,这些字段返回特定类型的数据。 例如,我们要创建一个 User 类型,我们应该有一些 nameemailage 字段。 类型字段可以是任何类型,并始终返回一种数据类型,如 Int,Float,String,Boolean,ID,对象类型列表或自定义对象类型。

现在编写的第一个 Type,在 schema.graphql 文件中用以下内容替换已存在的 Query 类型:

type User {
  id: ID!
  name: String!
  email: String!
  age: Int
}

每个用户都将拥有一个 ID,因此为其提供了 ID 类型。 用户也会有一个 nameemail,所以给它一个字符串类型和一个 Int 类型。

但是,在每一行的结尾的 呢? 感叹号表示字段不可为空,这意味着每个字段必须在每个查询中返回一些数据。 User 中唯一可以为空的字段是 age

在GraphQL中,有三个主要概念:

query (查询) — 从服务器获取数据的方式。

mutation (更改) — 修改服务器上的数据并获取更新数据的方法(创建、更新、删除)。

subscription (订阅) — 当希望数据更改时,可以进行消息推送,使用 subscription 类型(针对当前的日趋流行的 real-time 应用提出的)。

query (查询)

为了简单地解释这一点,GraphQL 中的查询是获取数据的方式。关于 GraphQL 中的查询,最吸引人的地方之一就是你将获得所需的确切数据,不多不少。这对我们的 API 产生了巨大的积极影响——不再像 REST API 那样获取过多或不足的信息。

我们将在 GraphQL 中创建第一个类型的 Query。 我们所有的查询都将以此类型结束。 首先,在文件 schema.graphql 编写一个名为Query 的新类型:

type Query {
  users: [User!]!
}

这很简单:用户查询将返回给我们一个或多个用户的数组。 它不会返回 null,因为我们放入了 ! ,这意味着它是一个不可为空的查询, 它总会返回一些数据。

但我们也可以返回特定用户。 为此,创建一个名为 user 的新查询。 在我们的 Query 类型中,写以下代码:

user(id: ID!): User!

现在 Query 类型应该是这样的:

type Query {
  users: [User!]!
  user(id: ID!): User!
}

如上所见,使用 GraphQL 中的查询,还可以传递参数。在本例中,要查询特定用户,所以要传递其用户的 ID。

但是,你可能想知道: GraphQL 如何知道从哪里获取数据? 这就是为什么我们应该有一个 resolvers.js 文件。该文件告诉 GraphQL 它将如何以及在何处获取数据。

首先,看看我们的 resolvers.js 文件并里该文件里导入 db.js 文件。我们刚才创建的 resolvers.js 文件内容如下:

import { users } from "./db";

const resolvers = {
  Query: {
    hello: () => "Hello World!"
  }
};

export default resolvers;

现在,我们将创建第一个 Query,在 resolvers.js 文件并替换 hello 函数。 现在 resolvers.js 内容如下 :

import { users } from "./db";

const resolvers = {
  Query: {
    user: (parent, { id }, context, info) => {
      return users.find(user => user.id == id);
    },
    users: (parent, args, context, info) => {
      return users;
    }
  }
};

export default resolvers;

现在,解释它是如何工作的:

每个查询解析器都有四个参数。 在 user 函数中,我们将 id 作为参数传递,然后返回与传递的 id 匹配的特定 user,这很简单。

users 函数中,我们只是返回已存在的 users 数组,这个数组存放的是所有的用户。

现在,我们将测试查询是否工作正常,转到 localhost:4000,输入以下代码:

query {
  users {
    id
    name
    email
    age
  }
}

它应该返回给你我们所有的用户。

如果想返回特定的用户:

query {
  user(id: 1) {
    id
    name
    email
    age
  }
}

mutation (更改)

在 GraphQL 中,更改是修改服务器上的数据并获取更新数据的方式, 你可以像 REST 的CUD(创建,更新,删除)一样思考。

在 GraphQL 中创建我们的第一个类型修改,这里所有的修改都将在这个类型中结束。 首先,在 schema.graphql文件中编写一个名为mutation 的新类型:

type Mutation {
  createUser(id: ID!, name: String!, email: String!, age: Int): User!
  updateUser(id: ID!, name: String, email: String, age: Int): User!
  deleteUser(id: ID!): User!
}

这里主要定义三个修改数据的方法:

createUser:传入需要创建用户的 ID,name,email 和 age,它会返回一个新用户给我们。

updateUser:传入需要修改用户的 ID,name,email 和 age(非必传),它会返回一个新用户给我们。

deleteUser: 传入需要删除用户的 ID,它会返回一个新用户给我们。

现在,在 resolvers.js 文件并在 Query 对象下面,创建一个新的 mutation 对象,如下所示:

Mutation: {
    createUser: (parent, { id, name, email, age }, context, info) => {
      const newUser = { id, name, email, age };

      users.push(newUser);

      return newUser;
    },
    updateUser: (parent, { id, name, email, age }, context, info) => {
      let newUser = users.find(user => user.id === id);

      newUser.name = name;
      newUser.email = email;
      newUser.age = age;

      return newUser;
    },
    deleteUser: (parent, { id }, context, info) => {
      const userIndex = users.findIndex(user => user.id === id);

      if (userIndex === -1) throw new Error("User not found.");

      const deletedUsers = users.splice(userIndex, 1);

      return deletedUsers[0];
    }
  }

现在 resolvers.js 文件内容如下:

import { users } from "./db";

const resolvers = {
  Query: {
    user: (parent, { id }, context, info) => {
      return users.find(user => user.id == id);
    },
    users: (parent, args, context, info) => {
      return users;
    }
  },
  Mutation: {
    createUser: (parent, { id, name, email, age }, context, info) => {
      const newUser = { id, name, email, age };

      users.push(newUser);

      return newUser;
    },
    updateUser: (parent, { id, name, email, age }, context, info) => {
      let newUser = users.find(user => user.id === id);

      newUser.name = name;
      newUser.email = email;
      newUser.age = age;

      return newUser;
    },
    deleteUser: (parent, { id }, context, info) => {
      const userIndex = users.findIndex(user => user.id === id);

      if (userIndex === -1) throw new Error("User not found.");

      const deletedUsers = users.splice(userIndex, 1);

      return deletedUsers[0];
    }
  }
};

export default resolvers;


现在,我们要测试我们的 mutations 是否正常。转到localhost:4000,输入以下代码:

mutation {
  createUser(id: 3, name: "Robert", email: "robert@gmail.com", age: 21) {
    id
    name
    email
    age
  }
}

subscription (订阅)

如我之前所说,订阅是你与服务器保持实时连接的方式。这意味着无论何时在服务器中发生事件,并且每当调用该事件时,服务器都会将相应的数据发送到客户端。

通过订阅,你可以让你的应用在不同的用户之间保持更新。

基本订阅是这样的:(sample.graphql )

subscription {
  users {
    id
    name
    email
    age
  }
}

你会说它非常类似于查询,是的, 但它的工作方式不同。

当服务器中发生更新时,服务器将运行订阅中指定的 GraphQL 查询,并向客户机发送一个新更新的结果。

在这篇文章中,我们不打算讨论订阅,但是如果你想阅读更多关于订阅的信息,请单击这里。

总结

如你所见,GraphQL 是一项非常强大的新技术。 它为我们提供了构建更好和精心设计的API的真正能力。 这就是为什么作者建议你现在开始学习它,从本文本作者的角度来说,它最终将取代 REST。


原文:

https://medium.freecodecamp.o...

你的点赞是我持续分享好东西的动力,欢迎点赞!

交流

干货系列文章汇总如下,觉得不错点个Star,欢迎 加群 互相学习。

https://github.com/qq44924588...

我是小智,公众号「大迁世界」作者,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!

关注公众号,后台回复福利,即可看到福利,你懂的。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72934.html

相关文章

  • GraphQL一个简单入门示例

    摘要:本文首发于个人博客目录什么是解决了什么问题一个简单的入门示例什么是官方文档定义一种用于的查询语言,有以下特点请求你所要的数据不多不少获取多个资源只用一个请求描述所有可能的类型系统解决了什么问题来说一个实际的场景前后端联调接口一直以来都是特别 本文首发于个人博客 目录 什么是GraphQL 解决了什么问题 GraphQL一个简单的入门示例 什么是GraphQL 官方文档定义:一种用...

    Pines_Cheng 评论0 收藏0
  • GraphQL入门到实践

    摘要:本文实例代码什么是是一种面向数据的查询风格。概述前端的开发随着框架全面普及,组件化开发也随之成为大势所趋,各个组件分别管理着各自的状态,组件化给前端仔带来便利的同时也带来了一些烦恼。 showImg(https://segmentfault.com/img/remote/1460000018479542?w=4928&h=3280); 本文首先介绍了 GraphQL,再通过 Mongo...

    Blackjun 评论0 收藏0
  • Gatsby极速入门—使用GraphQL解析Markdown(2)

    摘要:什么是既是一种用于的查询语言也是一个满足你数据查询的运行时。嵌套将组件扔到下面的里面打开首页,看到网站的描述就大功告成了。 1.什么是GraphQL GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间...

    fou7 评论0 收藏0
  • GraphQL 搭配 Koa 最佳入门实践

    摘要:如下图嗯,如图都已经查询到我们保存的全部数据,并且全部返回前端了。如图没错,什么都没有就是查询服务的界面。写好了之后我们在配置一下路由,进入里面,加入下面几行代码。 GraphQL一种用为你 API 而生的查询语言,2018已经到来,PWA还没有大量投入生产应用之中就已经火起来了,GraphQL的应用或许也不会太远了。前端的发展的最大一个特点就是变化快,有时候应对各种需求场景的变化,不...

    MoAir 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<