3. 更新代码
3m

更新代码

我们已经有了所需的包,现在开始替换它们。一个不错的选择是从src/index.js - 我们AS3服务器代码的位置!

src/index.js
const { ApolloServer } = require("apollo-server");
const typeDefs = require("./schema");
const resolvers = require("./resolvers");
const TrackAPI = require("./datasources/track-api");
async function startApolloServer(typeDefs, resolvers) {
const server = new ApolloServer({
typeDefs,
resolvers,
dataSources: () => {
return {
trackAPI: new TrackAPI(),
};
},
});
const { url, port } = await server.listen();
console.log(`
🚀 Server is running
🔉 Listening on port ${port}
📭 Query at ${url}
`);
}
startApolloServer(typeDefs, resolvers);

新导入

首先,让我们更新ApolloServer的导入语句,使其使用新的@apollo/server包。

src/index.js
- const { ApolloServer } = require("apollo-server");
+ const { ApolloServer } = require("@apollo/server")

作为AS4升级的一部分,@apollo/server包包含多个新的、更小的包,我们可以访问这些实用程序和函数以自定义服务器运行方式。我们仍然会使用已导入的ApolloServer类,但需要另一个额外函数startStandaloneServer

我们可以通过一个新的导入来访问startStandaloneServer函数,它针对的是位于@apollo/server包中的/standalone目录下的函数。

src/index.js
const { ApolloServer } = require("@apollo/server");
const { startStandaloneServer } = require("@apollo/server/standalone");
const typeDefs = require("./schema");
// other imports...

配置我们的服务器

startStandaloneServer

为了将startStandaloneServer函数与现有的服务器实现集成,我们需要进行一些更新。

我们可以删除的第一行是我们的server.listen()调用。我们将不再直接监听服务器实例,而是使用startStandaloneServer函数。

src/index.js
// ... imports
async function startApolloServer(typeDefs, resolvers) {
const server = new ApolloServer({
typeDefs,
resolvers,
dataSources: () => {
return {
trackAPI: new TrackAPI(),
};
},
});
- const { url, port } = await server.listen();
console.log(`
🚀 Server is running
🔉 Listening on port ${port}
📭 Query at ${url}
`);
}
startApolloServer(typeDefs, resolvers);

我们可以将要传递我们的已初始化的server常量作为参数的startStandaloneServer调用的结果。

src/index.js
// ... imports
async function startApolloServer(typeDefs, resolvers) {
const server = new ApolloServer({
typeDefs,
resolvers,
dataSources: () => {
return {
trackAPI: new TrackAPI(),
};
},
});
await startStandaloneServer(server);
console.log(`
🚀 Server is running
🔉 Listening on port ${port}
📭 Query at ${url}
`);
}
startApolloServer(typeDefs, resolvers);

从该调用的结果中,我们可以获取服务器运行在其上的url

src/index.js
const { url } = await startStandaloneServer(server);

context 函数

startStandaloneServer 可以接受第二个 ,这是一个配置对象,使我们能够自定义一些服务器功能。让我们先添加这个配置对象的括号。

src/index.js
const { url } = await startStandaloneServer(server, {
// configuration details
});

之前,我们在 ApolloServer 类的构造函数中直接定义了 dataSources。从该函数返回的数据成为了我们 在其第三个位置 context 参数

在 AS4 中,这个定义移动到了带有 context 键的 startStandaloneServer 配置对象中,它是一个异步函数。

现在让我们添加这个键

src/index.js
const { url } = await startStandaloneServer(server, {
context: async () => {},
});

在这个函数中,我们将返回一个对象。这是我们 在第三个 中收到的对象。

src/index.js
const { url } = await startStandaloneServer(server, {
context: async () => {
return {};
},
});

注意: 在 AS3 中,我们称解析器函数收到的第三个位置 context。在 AS4 中,我们按照惯例现在称该 context 函数返回的对象为 contextValue。这是因为当我们调用服务器配置中的 context 函数时,该 返回的对象 到达我们的 ' 第三个位置 参数

现在,让我们删除在 ApolloServer 实例化中定义的 dataSources 定义。取而代之,我们可以在 context 函数返回的对象中定义一个 dataSources 键。我们将 dataSources 设置为一个对象。

src/index.js
// ... imports
const server = new ApolloServer({
typeDefs,
resolvers,
- dataSources: () => {
- return {
- trackAPI: new TrackAPI(),
- };
- },
});
const { url } = await startStandaloneServer(server, {
context: async () => {
return {
+ dataSources: {}
}
}
})

最后,我们可以将 trackAPI 键和 TrackAPI 类的实例化移动到 dataSources 对象中。

src/index.js
const { url } = await startStandaloneServer(server, {
context: async () => {
return {
dataSources: {
trackAPI: new TrackAPI(),
},
};
},
});

注意: 在 AS3 中,dataSources 被定义为返回包含我们想要我们的 的对象的功能。在 AS4 中,dataSources 设置为包含这些 属性的对象。确保您的 dataSources 对象与上面所示的实施相匹配!

连接缓存

当我们使用 Apollo Server 3 时,为每个创建的 调用了 initialize 函数,将 Apollo Servercachecontext 作为参数传递,以便使它们可用于使用。在 Apollo Server 4 中,我们将自己处理这个问题。我们不需要我们的 TrackAPI 类能访问任何额外的 context 信息(如用户身份验证令牌),因此我们确保只传递从服务器初始化时得到的 cache

首先,我们需要获取对 cache 的访问权限。在 AS4 中,这作为服务器上只读的 提供的。让我们先解构我们的 server 以获取访问 cache 的权限。

src/index.js
const { url } = await startStandaloneServer(server, {
context: async () => {
const { cache } = server;
return {
dataSources: {
trackAPI: new TrackAPI(),
},
};
},
});

接下来,我们将更新我们的 TrackAPI 类实例化,传递一个包含 cache 的对象。

src/index.js
const { url } = await startStandaloneServer(server, {
context: async () => {
const { cache } = server;
return {
dataSources: {
trackAPI: new TrackAPI({ cache }),
},
};
},
});

太好了!这是我们配置在 AS4 中的 !我们的跟踪数据现在将可用于我们的 函数。

清理

以下是我们的服务器当前状态:

src/index.js
const { ApolloServer } = require("@apollo/server");
const { startStandaloneServer } = require("@apollo/server/standalone");
const typeDefs = require("./schema");
const resolvers = require("./resolvers");
const TrackAPI = require("./datasources/track-api");
async function startApolloServer(typeDefs, resolvers) {
const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await startStandaloneServer(server, {
context: async () => {
const { cache } = server;
return {
dataSources: {
trackAPI: new TrackAPI({ cache }),
},
};
},
});
console.log(`
🚀 Server is running
🔉 Listening on port ${port}
📭 Query at ${url}
`);
}
startApolloServer(typeDefs, resolvers);

我们已经完成了大部分代码更新,但仍需进行一些调整。目前,我们的 console.log 语句正在查找一个 port 。如你所见,我们不再从我们的服务器中提取这个值。

相反,让我们在我们的文件顶部定义一个 port ,并确保我们的实现能够从 process.env.PORT 读取(如果服务器运行的环境默认设置了该环境变量)。如果不存在这样的 PORT ,我们可以将其设为默认值 4000

const port = process.env.PORT || 4000;

我们可以让服务器读取这个 port 值,通过在 startStandaloneServer 配置对象中定义一个 listen 键。

我们将为 listen 的值设置一个带有 port 键的对象。由于键的名称与我们想要的值名称匹配,我们可以使用 ES6 简写语法,只需一次性设置键和值即可使用 port

src/index.js
+ const port = process.env.PORT || 4000;
async function startApolloServer(typeDefs, resolvers) {
const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await startStandaloneServer(server, {
context: async () => {
const { cache } = server;
return {
dataSources: {
trackAPI: new TrackAPI({ cache }),
},
};
},
+ listen: { port },
});
}

这就是服务器的更新内容... 但如果你在终端中运行 npm start,你仍然会看到一些错误!我们的应用的其他部分仍在使用 AS3 更旧的包。让我们再处理这些。

<上一步

分享你对这个课程的疑问和评论

你的反馈帮助我们改进!如果你遇到了困难或困惑,请告诉我们,我们会提供帮助。所有评论都是公开的,必须遵循 Apollo 行为准则。注意,已经解决或处理的评论可能会被删除。

你需要在下方发表评论时有一个 GitHub 账户。还没有吗? 请在我们的 Odyssey 论坛上发表帖子。