3. 字段弃用
5

概览

我们从打算对.

在本课中,我们将

  • 学习在我们的架构中替换 的过程
  • 了解 的用途
  • 使用@deprecated 在我们架构中的

迄今为止的架构

一个日益发展的 的常见情况是在架构中弃用现有 ,转而采用新字段。我们将在 Poetic Plates 中调查一个这样的情况

以下展示 Ingredient 类型的架构:

type Ingredient {
id: ID!
"Display text for the ingredient"
text: String
"The name of an ingredient"
name: String
"A potential substitute for the ingredient, if available"
substitute: String
}

用户反馈表示,对于 textname ,他们产生了混淆。

我们来看看这些 返回哪些值。使用 的 Explorer,运行以下 ,以检索随机食谱的成分列表。

query GetRandomRecipeIngredients {
randomRecipe {
ingredients {
text
name
}
}
}

根据你随机收到的食谱,你的响应可能有所不同,但以下是对我们接收到的内容的摘录

{
"data": {
"randomRecipe": {
"ingredients": [
{ "text": "1 cup onions, medium diced", "name": "onions" },
{ "text": "2 tbsp olive oil", "name": "olive oil" }
// ...
]
}
}
}

你看到 textname 之间的区别了吗?

它看起来像 text 返回有关成分的更长更详细的版本。 name 仅返回成分是什么,没有任何其他详细信息,如数量或如何准备。

深入研究架构中每个 的说明,文档中并没有明确说明这是用户应该预期的。因此我们可以理解用户在使用这些字段时存在的困惑。

我们应该修复架构中的描述,以便更清楚地说明每个预期会返回什么。我们还可以改进架构,更明确地说明text 返回什么。也许存在一个更好的的名称

此操作需要对我们的架构进行更改,但我们不希望删除text ,并一次性将其替换为新的字段。这样做将中断现有查询客户端正在发送的内容,我们不想让任何人担心

以下是计划

  1. 将新添加到架构中。
  2. 将旧标记为已弃用。
  3. 监视旧的使用情况
  4. 只要使用率下降,并且客户端有足够的时间进行更改,就可以安全地移除旧

让我们开始吧

向架构中添加新字段

首先,让我们将新添加到架构中。

  1. 在代码编辑器中打开配方资料库,并导航到schema.graphql文件。

  2. 找出 Ingredient 类型,并添加一个新的 ,称为 detailedDescription。这个 名称 非常 清晰,远胜于 text!它返回一个 String 类型,我们还可以为其赋予一个准确的描述,辅以一个示例。

    schema.graphql
    """
    A detailed description of the ingredient needed in the recipe.
    Usually in the format of: <QUANTITY> <INGREDIENT NAME>, <SPECIAL INSTRUCTIONS>.
    For example: 1 cup onions, medium diced
    """
    detailedDescription: String

添加新的解析器

我们将需要一个 用于这个新的 。我们的 并未提供此 detailedDescription 属性。没关系,它无需与我们的架构的 一一匹配。这就是 的妙处!

  1. 打开 src/resolvers/Ingredient.js 文件。

  2. Ingredient 对象下添加一个新属性,其名称与 相同,即 detailedDescription。它将设置到我们的 函数中。

    src/resolvers/Ingredient.js
    module.exports = {
    Ingredient: {
    detailedDescription: () => {},
    },
    };

    请记住,此 的值将与 text 的值完全相同。因此,我们需要获取该 text 值并从 detailedDescription 中返回该值。

    我们可以使用 text 值来访问 的第一个参数,parent,这是由于 链。

  3. detailedDescription 中,我们将解构第一个参数(parent)以获取 text 属性。我们不需要任何其他 参数,并将直接在 主体中返回该 text 值。

    src/resolvers/Ingredient.js
    detailedDescription: ({ text }) => text,

    这是我们照顾好的新

测试我们的更改

让我们确保新架构添加工作正常。

如果您的服务器未运行,您可以使用npm run dev启动它。这将在https://127.0.0.1:4001启动服务器。让我们在浏览器中访问那里,使用 Sandbox 来测试

我们应该看到新的 detailedDescription显示在左侧的文档面板上。

让我们尝试这个 检索一个随机菜谱及其成分: textdetailedDescription

query GetRandomRecipeIngredients {
randomRecipe {
ingredients {
text
detailedDescription
}
}
}

当我们获取数据后,我们应该看到 textdetailedDescription 的值相同。

一切都按预期进行!接下来,我们需要将 text 标记为已弃用。

@deprecated 指令

对于我们的用例,我们将使用 的一个默认 @deprecated

Illustration showing the syntax for the deprecated directive in a schema

我们对 @deprecated 应用于 ,以表明该 已...弃用!我们应该始终将 reason 传递给该指令,其中说明了弃用原因以及客户端应该改用哪个 。这是对 你的 的客户端的有用的信息。

Illustration showing the syntax for using the deprecated directive in the schema with the reason argument

使用 @deprecated 指令

  1. 再次打开 schema.graphql 文件。

  2. 找到 Ingredient 类型中的 text 。在 text 的返回类型后,我们将添加 @deprecated ,其中 reason"Use detailedDescription"

    Ingredient.text 现在应该如下所示:

    schema.graphql
    "Display text for the ingredient"
    text: String @deprecated(reason: "Use detailedDescription")

然后我们就完成了!

测试我们的更改

那么发生了什么变化?让我们找出来!你的服务器应该仍在运行并获取最新更改(如果不是,请确保再次运行 npm run dev)。返回 https://127.0.0.1:4001

查看我们之前相同的 ,你现在可以看到几个更改!

https://127.0.0.1:4001

Sandbox Explorer showing a deprecated message for the text field

首先,text 显示带下划线的黄色波浪线,如果将鼠标悬停在其上,我们将看到原因!该字段已弃用,就像我们在模式中标记的那样。我们还可以在左侧的文档面板上看到相同的消息。

我们仍然可以毫无问题地运行,但该警告旨在让我们知道我们真的不应该在我们的查询中再包含text

练习

模式指令
模式指令以 
 
 字符开头,它可以出现在模式中的特定符号之后,例如
 
 或
 
。默认指令的一个示例是
 
,它表示不再使用字段。此指令通常与 
 
 参数一起使用,以指定为什么不应使用该字段,或应使用哪个字段。

将此框中的项目拖动到上方的空白处

  • 原因

  • 解析器

  • 字段

  • @deleted

  • 说明

  • 类型

  • !

  • @deprecated

  • 消息

  • @

在从模式中删除字段之前,我们应该采取哪些措施?

关键要点

  • 要替换在我们的模式中,我们应该:
    • 添加新的
    • 将旧的标记为已弃用
    • 监视旧的使用情况
    • 只要使用率下降,并且客户端有足够的时间进行更改,就可以安全地移除旧
  • 架构指令是用@ 字符表示的,它装饰架构中特定的符号,例如类型或定义。
  • 要弃用,我们使用了默认的 @deprecatedreason 以让我们的使用者知道原因和哪个应该在替代方案中使用。
  • 我们依然可以使用被弃用的运行查询,但是弃用状态是提示我们要停止在现有查询中使用该字段的信号。

下一步

我们已经完成了此计划的前两个步骤,但这都是在我们的本地环境中进行的。我们需要让了解这些更改!

在接下来的两节课中,我们将了解如何使用安全、自信地落地这些更改。

上一步

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

本课程目前处于

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

你需要一个 GitHub 帐户才能在下面发帖。还没有吗? 转而在我们的 Odyssey 论坛中发帖。