5. Apollo Server
4m

🛠 后端第一步

在后端,我们的第一个目标是创建一个,它可以:

  1. 接收来自客户端的
  2. 根据我们新创建的 Schema 验证
  3. 用模拟数据填充查询到的 Schema
  4. 将填充后的 作为响应返回

The Apollo Server 库帮助我们快速、轻松地以生产就绪的方式实现此服务器。

server/src/ 文件夹中,打开 index.js.

要创建服务器,我们将使用之前安装的 @apollo/server 包。从该包中,我们只需要命名导出 ApolloServer,因此我们将在大括号之间声明该常量。

我们还需要使用 startStandaloneServer 函数,可以从 @apollo/server/standalone 包中导入。

在下方,我们将从 schema.js 文件中导入我们的 typeDefs

const { ApolloServer } = require("@apollo/server");
const { startStandaloneServer } = require("@apollo/server/standalone");
const typeDefs = require("./schema");

接下来,让我们设置一个 async 函数,名为 startApolloServer。在内部,我们将创建一个 ApolloServer 类的实例,并在其选项对象中传递我们的 typeDefs

async function startApolloServer() {
const server = new ApolloServer({ typeDefs });
}

注意: 我们使用简写属性表示法,并带有隐式键,因为我们已用匹配的键(typeDefs)命名了我们的常量。

要启动服务器,我们将使用 startStandaloneServer 函数,并将我们刚刚初始化的 server 传递给它。

async function startApolloServer() {
const server = new ApolloServer({ typeDefs });
startStandaloneServer(server);
}

The startStandaloneServer 函数返回一个 Promise,因此我们将 await 该调用的结果,并从结果中提取 url 属性。

async function startApolloServer() {
const server = new ApolloServer({ typeDefs });
const { url } = await startStandaloneServer(server);
}

我们还将记录一条友好的信息,让我们知道我们的服务器确实已启动并运行!

async function startApolloServer() {
const server = new ApolloServer({ typeDefs });
const { url } = await startStandaloneServer(server);
console.log(`
🚀 Server is running!
📭 Query at ${url}
`);
}

最后,别忘了在文件底部实际调用 startApolloServer 函数!

startApolloServer();

保存更改。从终端,我们将 我们的服务器,使用 npm run start (确保你在 server/ 文件夹中)。

我们得到日志信息,以及...没有别的!我们有一个正在运行的服务器,仅此而已。它漂浮在 localhost 空间的真空中,无法访问任何数据,现在它是一个悲伤而孤独的服务器。 😿

以下哪些是 GraphQL 服务器的目的?

即使我们的服务器尚未连接到任何 ,能够向服务器发送测试 并获得有效响应将非常有用。幸运的是, ApolloServer 提供了一种使用 模拟数据 完成此操作的方法。

模拟数据

要启用模拟数据,我们需要使用两个新的包: @graphql-tools/mock@graphql-tools/schema.

让我们继续安装它们。

npm install @graphql-tools/mock @graphql-tools/schema

在顶部,我们将导入 addMocksToSchemamakeExecutableSchema.

const { addMocksToSchema } = require("@graphql-tools/mock");
const { makeExecutableSchema } = require("@graphql-tools/schema");

然后,我们需要调整 ApolloServer 初始化。我们将不再直接传递 typeDefs,而是使用 schema 属性。此属性是初始化 的另一种方式,这对于构建联合 在我们的 Voyage 系列中了解更多)或如果我们使用诸如 makeExecutableSchema 之类的函数(我们确实使用它!)。

作为 schema 属性的值,我们将调用 addMocksToSchema 函数并传递一个对象。此对象定义了它自己的 schema 属性,在这里我们将调用 makeExecutableSchema 函数。然后,我们将向此函数传递一个包含我们的 typeDefs 的对象。

const server = new ApolloServer({
schema: addMocksToSchema({
schema: makeExecutableSchema({ typeDefs }),
}),
});

使用此代码,我们正在从 typeDefs 生成一个可执行的 Schema,并指示 用占位符值(例如,对于 String 使用 Hello World)填充每个查询到的 Schema

但是,Hello World 对于歌曲标题或作者图片的 URL 并不是一个非常现实的值!为了提供更接近现实的模拟数据,我们将定义一个 mocks 对象。此对象包含函数,这些函数提供我们希望服务器为每个查询到的 返回的模拟数据。

这是我们的 mocks 对象:

const mocks = {
Track: () => ({
id: () => "track_01",
title: () => "Astro Kitty, Space Explorer",
author: () => {
return {
name: "Grumpy Cat",
photo:
"https://res.cloudinary.com/dety84pbu/image/upload/v1606816219/kitty-veyron-sm_mctf3c.jpg",
};
},
thumbnail: () =>
"https://res.cloudinary.com/dety84pbu/image/upload/v1598465568/nebula_cat_djkt9r.jpg",
length: () => 1210,
modulesCount: () => 6,
}),
};

此对象定义了 的模拟值,这些字段属于 Track 对象(包括它包含的 Author 对象)。我们将此对象传递给 ApolloServer 构造函数,如下所示:

const server = new ApolloServer({
schema: addMocksToSchema({
schema: makeExecutableSchema({ typeDefs }),
mocks,
}),
});

启用模拟后, 始终为每个列表 返回正好两项。
要一次获取更多项,比如 6 项,我们将向 mocks 对象添加一个 Query.tracksForHome,并像这样返回一个给定长度的数组: [...new Array(6)].

const mocks = {
Query: () => ({
tracksForHome: () => [...new Array(6)],
}),
Track: () => ({
id: () => "track_01",
title: () => "Astro Kitty, Space Explorer",
author: () => {
return {
name: "Grumpy Cat",
photo:
"https://res.cloudinary.com/dety84pbu/image/upload/v1606816219/kitty-veyron-sm_mctf3c.jpg",
};
},
thumbnail: () =>
"https://res.cloudinary.com/dety84pbu/image/upload/v1598465568/nebula_cat_djkt9r.jpg",
length: () => 1210,
modulesCount: () => 6,
}),
};
以下哪些关于在没有连接数据源的情况下查询 Apollo Server 的说法是正确的?
代码挑战!

创建一个模拟对象,类型为 SpaceCatid 为 spacecat_01,title 为 'spacecat pioneer'

加载中...
加载进度

现在,我们的服务器已经加载了模拟数据,我们如何运行一个 来测试它是否按预期工作?在下一课中,我们将使用 Apollo Explorer 无缝构建和运行测试查询。

上一页

分享您对此课程的疑问和评论

您的反馈有助于我们改进!如果您卡住了或感到困惑,请告诉我们,我们将帮助您解决。所有评论都是公开的,必须遵守 Apollo 行为准则。请注意,已解决或已处理的评论可能会被删除。

您需要一个 GitHub 帐户才能在下面发布。还没有吗? 请在我们的 Odyssey 论坛中发布。