13. 突变响应
5m

概述

到目前为止,我们只使用过一种类型的 :查询。这些是用于检索数据的只读操作。为了修改数据,我们需要使用另一种类型的 GraphQL 操作: ,即写操作。

在本课中,我们将学习关于设计 和突变响应的常见约定

突变

接下来我们将介绍 MusicMatcher 项目中的一个功能:将曲目添加到现有播放列表中。

让我们看看启用此功能的相应 REST API 方法POST /playlists/{playlist_id}/tracks

https://spotify-demo-api-fe224840a08c.herokuapp.com/v1/docs

Mock REST API with POST endpoint

从文档中,我们需要以下参数:

  • playlist_id - 播放列表的 ID,作为 string (必需)
  • position - 一个 integer,从零开始索引,表示我们要插入曲目(s)的位置
  • uris - 用逗号分隔的 string,包含我们想要添加的曲目的 uri

然后该方法将返回一个包含 snapshot_id 属性的对象,该属性表示此时播放列表的状态。

好的,现在如何在 中启用此功能?

设计突变

让我们从模式开始。

对于 名称,我们建议使用一个动词开头,描述更新操作的具体行为(例如添加、删除或创建),然后加上突变所作用的数据。

对于突变的返回类型,我们可以返回突变所作用的 。但是,我们建议遵循一致的 Response 类型用于突变响应。

突变响应

我们需要考虑可能出现的任何部分错误,并向客户端返回有用的信息。我们建议向所有突变响应添加三个常见

  • code:一个 int,用于引用响应的状态,类似于 HTTP 状态代码。
  • success:一个 bool 标志,指示突变负责的所有更新是否成功。
  • message:一个 string,用于在客户端显示有关突变结果的信息。如果突变仅部分成功,而通用的错误消息无法说明全部情况,那么这将特别有用。

然后,我们还将有一个 用于我们正在突变的 (在这种情况下为 Playlist)。在某些突变中,这可能是 多个 对象!

至于命名约定,返回类型通常以单词 PayloadResponse 结尾。

The AddItemsToPlaylistPayload type

遵循我们所涵盖的最佳实践,我们将命名我们的 AddItemsToPlaylist。让我们首先为这个突变创建返回类型: AddItemsToPlaylistPayload

Types 下,我们将创建一个名为 AddItemsToPlaylistPayload 的新类文件。

Types/AddItemsToPlaylistPayload.cs
namespace Odyssey.MusicMatcher;
public class AddItemsToPlaylistPayload
{
}

然后,我们将添加 codesuccessmessage 的属性。

Types/AddItemsToPlaylistPayload.cs
[GraphQLDescription("Similar to HTTP status code, represents the status of the mutation.")]
public int Code { get; set; }
[GraphQLDescription("Indicates whether the mutation was successful.")]
public bool Success { get; set; }
[GraphQLDescription("Human-readable message for the UI.")]
public string Message { get; set; }

在这种情况下,我们正在突变的对象是 Playlist 类型,它是可为空的,因为突变中可能会出现问题!

Types/AddItemsToPlaylistPayload.cs
[GraphQLDescription("The playlist that contains the newly added items.")]
public Playlist? Playlist { get; set; }

最后,我们将添加构造函数。请记住使 playlist 参数可为空!突变可能会失败,我们不会收到播放列表对象。

Types/AddItemsToPlaylistPayload.cs
public AddItemsToPlaylistPayload(int code, bool success, string message, Playlist? playlist)
{
Code = code;
Success = success;
Message = message;
if (playlist != null) {
Playlist = playlist;
}
}

新的入口点:Mutation

Types 下,我们将创建一个名为 Mutation 的新类文件。

Types/Mutation.cs
namespace Odyssey.MusicMatcher;
public class Mutation
{
}

接下来,我们将为 函数编写我们的 AddItemsToPlaylist 。它将返回 AddItemsToPlaylistPayload 类型。我们还将为它添加一个描述。

Types/Mutation.cs
[GraphQLDescription("Add one or more items to a user's playlist.")]
public AddItemsToPlaylistPayload AddItemsToPlaylist()
{
}

然后,我们现在将对 的结果进行硬编码。循序渐进!我们将创建一个新的 AddItemsToPlaylistPayload 实例,为 code 传入 200,为 success 状态传入 true,一个成功的 message 和一个硬编码的 Playlist 对象。

Types/Mutation.cs
return new AddItemsToPlaylistPayload(
200,
true,
"Successfully added items to playlist.",
new Playlist("6Fl8d6KF0O4V5kFdbzalfW", "Sweet Beats & Eats")
);

我们 需要知道这个新的模式入口点。与Query 类型类似,我们需要调用AddMutationType 上,并将Mutation 类型传入。

Program.cs
builder.Services
.AddGraphQLServer()
.AddQueryType<Query>()
.AddMutationType<Mutation>()
.RegisterService<SpotifyService>();

保存所有这些更改并重新启动服务器。

探索时间!

是时候让我们的 运转起来了!回到 Sandbox Explorer,我们将创建一个新的工作区选项卡。

Documentation 面板中,让我们导航回模式的根目录。在Query 旁边,我们可以看到Mutation 类型。

https://studio.apollographql.com/sandbox/explorer

Explorer - mutation added

让我们添加addItemsToPlaylist 以及其中的所有子字段。对于playlist,现在选择name

GraphQL 操作
mutation AddItemsToPlaylist {
addItemsToPlaylist {
code
message
success
playlist {
name
}
}
}

运行

https://studio.apollographql.com/sandbox/explorer

Explorer - mutation response

响应数据
{
"data": {
"addItemsToPlaylist": {
"code": "200",
"message": "Added items to playlist successfully",
"success": true,
"playlist": {
"name": "Sweet Beats & Eats"
}
}
}
}

响应类似,我们的 响应遵循与我们的 mutation 相同的形状!

练习

根据以上推荐的约定,以下哪些是好的 mutation 名称?
在 mutation 响应类型 (AddItemsToPlaylistPayload) 中,为什么修改后的对象的返回类型 (Playlist) 是可空的?

主要要点

  • 是用于修改数据的写入
  • 命名 通常以描述动作的动词开头,例如“添加”、“删除”或“创建”。
  • 响应创建一致的响应类型是一个普遍的约定。

接下来

我们将学习 输入的最佳实践,并返回真实数据。

上一节

分享您对本课的疑问和评论

本课程目前处于

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

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