使用Apollo创建GraphQL Service

安装

perl 复制代码
"@apollo/client": "^3.7.1",
"graphql": "^16.6.0",

@apollo/client: 这是Apollo Client的JavaScript库,用于在前端应用中管理GraphQL请求。Apollo Client是一个现代化的GraphQL客户端,它提供了强大的功能,包括数据缓存、实时更新、错误处理等。通过Apollo Client,你可以轻松地向GraphQL服务器发出查询和变更请求,并将响应的数据集成到你的前端应用中。版本号^3.7.1表示你的应用使用的是3.7.1版本的Apollo Client库。

graphql: 这是GraphQL查询语言的JavaScript解析器。GraphQL是一种用于API的查询语言,它允许客户端明确指定需要的数据结构,从而避免了传统REST API中可能存在的数据过载问题。GraphQL库提供了解析GraphQL查询字符串、验证查询的结构等功能。版本号^16.6.0表示你的应用使用的是16.6.0版本的GraphQL库。

这两个库的结合使用, @apollo/client用于发送和管理GraphQL请求,而graphql库则用于解析和验证GraphQL查询语言。在前端应用中,你可以使用Apollo Client来构建和发送GraphQL查询,并使用graphql库来解析从服务器返回的GraphQL响应。这样,你可以通过GraphQL与服务器进行灵活、高效的数据交互,而这两个库的版本号则表示你所使用的具体版本。

vite 支持 eslint

pnpm i vite-plugin-eslint -D

vite-plugin-eslint 是 Vite 构建工具的一个插件,用于集成 ESLint 到 Vite 项目中.

  • 代码质量检查: vite-plugin-eslint 可以帮助开发者在构建过程中对项目代码进行静态代码分析,以发现潜在的问题、代码风格不一致或错误。ESLint 是一个常用的 JavaScript/TypeScript 代码质量检查工具,它提供了大量的规则,用于检测和修复代码。
  • 自动修复: 除了检查代码,该插件还支持自动修复一些 ESLint 可以处理的问题。通过配置,它可以自动修复一些简单的代码问题,提高开发效率。
  • 集成到构建流程: vite-plugin-eslint 能够与 Vite 构建流程集成,确保在开发和生产环境中都能进行代码检查。这有助于在代码提交前或构建过程中发现潜在的问题,提高代码质量。

实现 graphql service 层

pnpm i @apollo/client graphql -S

初始化Apollo Client

新建utlis文件夹,以及apollo.ts,创建Apollo客户端实例。

javascript 复制代码
import { ApolloClient, InMemoryCache } from '@apollo/client';

export const client = new ApolloClient({
  uri: 'http://localhost:3000/graphql',
  cache: new InMemoryCache(),
});

import { ApolloClient, InMemoryCache } from '@apollo/client';: 这行代码引入了Apollo Client库中的ApolloClient和InMemoryCache两个类。ApolloClient用于创建一个Apollo客户端实例 ,而InMemoryCache是用于客户端内部缓存数据的缓存实现。

InMemoryCache 是 Apollo Client 提供的一种缓存实现,它用于在客户端内部缓存GraphQL查询的响应数据。这个缓存实现的主要作用是在客户端内存中维护一个数据存储,将从服务器获取的数据响应保存在内存中。当应用程序执行相同的GraphQL查询时,它会首先检查内存缓存中是否已经有了该查询的响应数据,如果有则直接返回缓存中的数据,避免了不必要的网络请求。

以下是 InMemoryCache 的主要特性和作用:

  • 缓存响应数据: 当应用程序发起GraphQL查询时,InMemoryCache 会将查询的响应数据缓存到内存中。这包括了查询的具体结果以及相应的数据标识(例如ID)。
  • 智能合并数据: 当多个组件发起相同查询时,InMemoryCache 会智能地将这些查询的响应数据进行合并。它使用数据标识(通常是ID)来判断哪些数据是相同的,从而避免了数据的冗余存储。
  • 快速读取数据: 由于数据保存在内存中,所以从缓存中读取数据非常迅速。这减少了应用程序的加载时间,提高了性能。
  • 减少网络请求: 通过在客户端内部缓存数据,可以减少对服务器的网络请求。只有在缓存中没有找到数据时,客户端才会向服务器发起请求。
  • 自动化的数据更新: 当应用程序修改了缓存中的数据,InMemoryCache 会自动通知相关的查询组件,以便它们可以重新渲染,并显示最新的数据。

总的来说,InMemoryCache 是 Apollo Client 的核心之一,它帮助应用程序有效地管理和利用从服务器获取的数据,提供了一种高效的方式来处理GraphQL查询的响应数据。

export const client = new ApolloClient({ uri: 'http://localhost:3000/graphql', cache: new InMemoryCache(), });: 这部分代码创建了一个新的Apollo客户端实例。在这个实例中,你配置了两个主要的参数:

  • uri: 'http://localhost:3000/graphql': 这个参数指定了GraphQL服务器的URL。Apollo Client将会向这个URL发送所有的GraphQL请求。在这个例子中,GraphQL服务器位于本地机器的端口3000上的'/graphql'路径。
  • cache: new InMemoryCache(): 这个参数指定了客户端的缓存实现。InMemoryCache是Apollo Client提供的一种缓存策略,它将在客户端内部缓存GraphQL查询的响应数据,以便在后续的查询中使用。通过使用缓存,可以避免不必要的网络请求,提高应用性能。

export const client: 最后,通过export关键字将创建好的Apollo客户端实例导出,使得其他文件可以引入并使用这个客户端实例来发送GraphQL请求。

总的来说,这段代码的作用是创建了一个Apollo Client实例,配置了GraphQL服务器的URL和缓存策略,使得你的前端应用可以使用这个客户端实例来与GraphQL服务器进行数据交互。

2.包裹ApolloProvider

javascript 复制代码
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ApolloProvider } from '@apollo/client';
import App from './App';
import './index.css';
import { client } from './utils/applo';

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
);

import { ApolloProvider } from '@apollo/client';: 这行代码引入了Apollo Client库中的ApolloProvider组件。ApolloProvider是Apollo Client提供的React组件,它用于将Apollo Client的实例传递给React应用的组件树,以便应用程序中的组件可以发起GraphQL查询。

import { client } from './utils/applo';: 这行代码引入了应用程序中用于与GraphQL服务器交互的Apollo Client实例,通常从./utils/applo文件中导出。

<ApolloProvider client={client}>, <App />: 这部分代码使用ApolloProvider组件包裹了应用程序的主组件。ApolloProvider组件接受一个client属性,该属性传递了应用程序与GraphQL服务器通信的Apollo Client实例。通过ApolloProvider,整个应用程序的组件树都可以访问到Apollo Client,可以发起GraphQL查询请求。

通过这段代码,整个React应用程序得以和Apollo Client连接,使得应用程序能够方便地发起GraphQL查询请求,并且将查询的数据集成到React组件中,实现前端与GraphQL服务器的数据交互。

3.定义gql schema

创建文件夹

javascript 复制代码
import { gql } from '@apollo/client';

export const FIND = gql`
query find($id: String!){
    find(id: $id){
          name
      desc
    }
  }
`;

这段代码使用了Apollo Client库中的gql函数,它用于定义GraphQL查询。

import { gql } from '@apollo/client';: 这行代码引入了Apollo Client库中的gql函数。gql函数是一个用于解析GraphQL查询字符串的函数,它可以将一个字符串转换为GraphQL AST(Abstract Syntax Tree)。

`` export const FIND = gql...` ```: 这部分代码定义了一个GraphQL查询。在这个例子中,定义了一个名为FIND的GraphQL查询,它使用GraphQL模板字符串的语法,包裹了一个具体的查询字符串。这个查询的目的是根据提供的id参数查询特定用户的name和desc字段。

中间的代码可以在GraphQL调试面板复制

javascript 复制代码
query find($id: String!){
find(id: $id){
name
desc
}
}

query find($id: String!): 这行代码定义了一个GraphQL查询操作,命名为find。它接受一个名为id的参数,类型为字符串,表示要查询的用户的唯一标识。$id: String!中的!表示该参数是必需的。

{ find(id: $id) { name desc } }: 这部分代码指定了查询的具体操作。在find操作中,传入了id参数,并请求返回用户的name和desc字段。这里的name和desc是假设用户对象中包含的字段名。

4.使用useQuery,useMutation

在App.tsx中编写,

此时

javascript 复制代码
import { useQuery } from '@apollo/client';
import './App.css';
import { FIND } from './graphql/demo';

const App = () => {
  const { loading, data } = useQuery(FIND, {
    variables: {
      id: '22820297-e288-42ba-aadf-3a4062c5c3cb',
    },
  });
  return (
    <div>
      <p>
        data:
        {JSON.stringify(data)}
      </p>
      <p>{`${loading}`}</p>
    </div>
  );
};
export default App;

上述代码使用了Apollo Client中的useQuery hook,它是一个用于在React函数组件中执行GraphQL查询的钩子函数。

import { useQuery } from '@apollo/client';: 这行代码引入了Apollo Client库中的useQuery hook。useQuery hook允许在React函数组件中执行GraphQL查询,并处理查询的结果(例如加载状态、查询数据等)。

import { FIND } from './graphql/demo';: 这行代码引入了之前定义的GraphQL查询FIND。这个查询通常包含在一个单独的文件中(例如demo.js),然后被引入到应用程序中。

const { loading, data } = useQuery(FIND, { variables: { id: '22820297-e288-42ba-aadf-3a4062c5c3cb', }, });: 这行代码使用useQuery hook来执行GraphQL查询。useQuery接受两个参数:第一个参数是之前定义的GraphQL查询(在这里是FIND),第二个参数是一个对象,用于传递查询的变量(如果有的话)。

  • loading: 这是一个布尔值,表示查询是否仍在加载中。当loading为true时,表示查询尚未完成。
  • data: 这是包含查询结果的对象。当查询完成后,data中将包含从服务器返回的数据。

useQuery hook负责在组件挂载时(或者在查询变量发生变化时)发起GraphQL查询,并将查询的结果返回给组件。variables选项中指定了查询所需的变量,例如id的值。

通过这种方式,App组件可以根据loading状态显示加载指示器,然后使用data中的数据来渲染应用程序的UI,从而实现了与GraphQL服务器的数据交互和渲染。

运行结果如下:

具体的网络请求信息如下


视频插播

开启跨域限制:

javascript 复制代码
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableCors();
  await app.listen(3000);
}
bootstrap();

如果想允许部分地址可以跨域,需要这么写:

也可以配置的允许跨域的域名:

css 复制代码
app.enableCors({
   origin: 'http://localhost:5173',
});

编写update操作(使用useMutation)

编写对应的gql语句,定义了一个 GraphQL 变更(Mutation)查询,使用了 Apollo Client 提供的 gql 模板字符串。

php 复制代码
export const UPDATE = gql`
mutation update($id: String!, $params: UserInput!){
  update(id: $id, params: $params)
}
`;

```export const UPDATE = gql...`````: 这行代码定义了一个 GraphQL 变更操作,命名为 UPDATE。gql 函数用于将 GraphQL 查询字符串转换为 GraphQL AST(Abstract Syntax Tree),以便 Apollo Client 可以理解和发送到服务器。

mutation update($id: String!, $params: UserInput!): 这部分定义了一个 GraphQL 变更操作,命名为 update。它接受两个参数:$id(一个字符串)和 $params(一个类型为 UserInput 的输入对象)。这些参数是在调用这个变更操作时必须提供的, <math xmlns="http://www.w3.org/1998/Math/MathML"> i d 表示要更新的用户的唯一标识,而 id 表示要更新的用户的唯一标识,而 </math>id表示要更新的用户的唯一标识,而params 包含了更新用户时所需的各种属性(例如 name、email 等)。

update(id: $id, params: $params): 在变更操作的主体部分。

id: $id 表示使用传入的 $id 参数作为用户的唯一标识,

params: $params 表示使用传入的 $params 参数作为要更新的用户的属性。

<math xmlns="http://www.w3.org/1998/Math/MathML"> i d 和 id 和 </math>id和params是通过 Mutation 操作的参数传递给后端的实际值 。 <math xmlns="http://www.w3.org/1998/Math/MathML"> i d 对应了前面定义的 id 对应了前面定义的 </math>id对应了前面定义的id 输入参数, <math xmlns="http://www.w3.org/1998/Math/MathML"> p a r a m s 对应了 params 对应了 </math>params对应了params 输入参数。

这里的 update 是一个 GraphQL 变更(Mutation)操作的名称。在 GraphQL 中,update 是一个被服务器端实现的 Mutation 操作,用于执行数据的更新。

在前端应用程序中使用 Apollo Client 的 useMutation hook 方法时,需要提供一个包含相同变更操作名称(比如 update)的 Mutation 查询。这样,Apollo Client 就知道在发送请求时要将数据传递给服务器上名为 update 的变更操作。

在代码中,UPDATE 是一个 GraphQL 查询,它定义了一个名为 update 的 Mutation 操作。当你在前端应用程序中调用 useMutation hook时,你将使用这个 UPDATE 查询。例如,使用 useMutation hook 的方式可能如下:

这样定义了一个 GraphQL 变更查询后,可以在前端应用程序中使用 Apollo Client 的 useMutation hook 来执行这个变更操作,将更新的数据发送给服务器。这个查询使得前端应用程序能够与服务器进行双向数据交互,实现了数据的更新功能。

调用useMutation,返回update函数

sql 复制代码
import { FIND, UPDATE } from './graphql/demo';
const [update] = useMutation(UPDATE);

const [update] = useMutation(UPDATE);: 这行代码使用了useMutation hook,它是Apollo Client提供的一个React hook,用于执行GraphQL变更操作。在这里,useMutation hook接受了UPDATE变更操作作为参数,并返回一个数组,其中包含了一个函数(在这里命名为update)和其他一些属性。

update: 这是一个函数,用于触发GraphQL变更操作 。在这个例子中,它被赋值给[update]的左侧,表示我们只关心返回的第一个函数。当调用update函数时,它将发送UPDATE变更操作的请求到GraphQL服务器。你可以通过传递变更操作所需的参数来执行相应的数据更新。

总的来说,这段代码的作用是使用useMutation hook,将从'./graphql/demo'导入的UPDATE变更操作绑定到一个函数update上。这个函数可以在组件中被调用,用于触发GraphQL服务器上的相应数据更新操作。

编写按钮的事件监听函数,参数可以从Graph调试面板中复制,

php 复制代码
const onClickHandler = () => {
    update({
      variables: {
        id: '22820297-e288-42ba-aadf-3a4062c5c3cb',
        params: {
          desc,
          name,
        },
      },
    });
  };

update({ variables: { id: '22820297-e288-42ba-aadf-3a4062c5c3cb', params: { desc, name, }, }, });: 在onClickHandler函数中,update函数被调用,触发了GraphQL变更操作。这个操作的目的通常是将某个对象的属性更新为特定的值。

variables: { id: '22820297-e288-42ba-aadf-3a4062c5c3cb', params: { desc, name, }, },: 这是一个包含变更操作所需参数的对象。id参数是一个字符串,表示要更新的对象的唯一标识符。params参数是一个对象,包含了两个属性desc和name,它们的值通常来自于组件中的状态或者用户的输入。

update函数是之前使用useMutation hook从UPDATE变更操作中获得的。通过调用update函数并传入包含了所需参数的对象,GraphQL客户端将向服务器发起一个GraphQL变更请求,执行相应的操作。

最终效果如下:

执行后具体的网络请求信息

相关推荐
webxue1 天前
NestJS配置环境变量、读取Yaml配置的保姆级教程
node.js·nestjs
超级无敌暴龙兽4 天前
微服务架构的基础与实践:构建灵活的分布式系统
微服务·node.js·nestjs
寻找奶酪的mouse6 天前
【NestJS全栈之旅】应用篇:通用爬虫服务三两事儿
前端·后端·nestjs
_jiang8 天前
nestjs 入门实战最强篇
redis·typescript·nestjs
AiFlutter8 天前
Java对接GraphQL
java·开发语言·graphql
敲代码的彭于晏10 天前
【Nest.js 10】JWT+Redis实现登录互踢
前端·后端·nestjs
Elastic 中国社区官方博客15 天前
GraphQL 与 Elasticsearch 相遇:使用 Hasura DDN 构建可扩展、支持 AI 的应用程序
大数据·后端·elasticsearch·搜索引擎·全文检索·graphql·1024程序员节
罗小爬EX15 天前
GraphQL系列 - 第2讲 Spring集成GraphQL
spring·graphql
罗小爬EX15 天前
GraphQL系列 - 第1讲 GraphQL语法入门
数据库·后端·graphql
API开发15 天前
APISQL企业版离线部署教程
sql·node.js·api·restful·graphql·apisql