更新代码
我们已经有了所需的包,现在开始替换它们。一个不错的选择是从src/index.js
- 我们AS3服务器代码的位置!
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
包。
- const { ApolloServer } = require("apollo-server");+ const { ApolloServer } = require("@apollo/server")
作为AS4升级的一部分,@apollo/server
包包含多个新的、更小的包,我们可以访问这些实用程序和函数以自定义服务器运行方式。我们仍然会使用已导入的ApolloServer
类,但需要另一个额外函数startStandaloneServer
。
我们可以通过一个新的导入来访问startStandaloneServer
函数,它针对的是位于@apollo/server
包中的/standalone
目录下的函数。
const { ApolloServer } = require("@apollo/server");const { startStandaloneServer } = require("@apollo/server/standalone");const typeDefs = require("./schema");// other imports...
配置我们的服务器
startStandaloneServer
为了将startStandaloneServer
函数与现有的服务器实现集成,我们需要进行一些更新。
我们可以删除的第一行是我们的server.listen()
调用。我们将不再直接监听服务器实例,而是使用startStandaloneServer
函数。
// ... importsasync 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
调用的结果。
// ... importsasync 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
。
const { url } = await startStandaloneServer(server);
context
函数
startStandaloneServer
可以接受第二个 参数,这是一个配置对象,使我们能够自定义一些服务器功能。让我们先添加这个配置对象的括号。
const { url } = await startStandaloneServer(server, {// configuration details});
之前,我们在 ApolloServer
类的构造函数中直接定义了 dataSources
。从该函数返回的数据成为了我们 解析器 在其第三个位置 context
参数
在 AS4 中,这个定义移动到了带有 context
键的 startStandaloneServer
配置对象中,它是一个异步函数。
现在让我们添加这个键
const { url } = await startStandaloneServer(server, {context: async () => {},});
在这个函数中,我们将返回一个对象。这是我们 解析器 在第三个 参数中收到的对象。
const { url } = await startStandaloneServer(server, {context: async () => {return {};},});
注意: 在 AS3 中,我们称解析器函数收到的第三个位置 参数 为 context
。在 AS4 中,我们按照惯例现在称该 context
函数返回的对象为 contextValue
。这是因为当我们调用服务器配置中的 context
函数时,该 返回的对象 到达我们的 解析器' 第三个位置 参数
。
现在,让我们删除在 ApolloServer
实例化中定义的 dataSources
定义。取而代之,我们可以在 context
函数返回的对象中定义一个 dataSources
键。我们将 dataSources
设置为一个对象。
// ... importsconst server = new ApolloServer({typeDefs,resolvers,- dataSources: () => {- return {- trackAPI: new TrackAPI(),- };- },});const { url } = await startStandaloneServer(server, {context: async () => {return {+ dataSources: {}}}})
最后,我们可以将 trackAPI
键和 TrackAPI
类的实例化移动到 dataSources
对象中。
const { url } = await startStandaloneServer(server, {context: async () => {return {dataSources: {trackAPI: new TrackAPI(),},};},});
注意: 在 AS3 中,dataSources
被定义为返回包含我们想要我们的 数据源 的对象的功能。在 AS4 中,dataSources
设置为包含这些 数据源 属性的对象。确保您的 dataSources
对象与上面所示的实施相匹配!
连接缓存
当我们使用 Apollo Server 3 时,为每个创建的 数据源 调用了 initialize
函数,将 Apollo Server
的 cache
和 context
作为参数传递,以便使它们可用于使用。在 Apollo Server 4 中,我们将自己处理这个问题。我们不需要我们的 TrackAPI
类能访问任何额外的 context
信息(如用户身份验证令牌),因此我们确保只传递从服务器初始化时得到的 cache
。
首先,我们需要获取对 cache
的访问权限。在 AS4 中,这作为服务器上只读的 变量 提供的。让我们先解构我们的 server
以获取访问 cache
的权限。
const { url } = await startStandaloneServer(server, {context: async () => {const { cache } = server;return {dataSources: {trackAPI: new TrackAPI(),},};},});
接下来,我们将更新我们的 TrackAPI
类实例化,传递一个包含 cache
的对象。
const { url } = await startStandaloneServer(server, {context: async () => {const { cache } = server;return {dataSources: {trackAPI: new TrackAPI({ cache }),},};},});
太好了!这是我们配置在 AS4 中的 数据源!我们的跟踪数据现在将可用于我们的 解析器 函数。
清理
以下是我们的服务器当前状态:
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
。
+ 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 论坛上发表帖子。