参加10月8日至10日在纽约市的活动,了解有关 GraphQL 联盟和 API 平台工程的最新技巧、趋势和新闻。参加2024年在纽约市的 GraphQL 大会
文档
免费开始
您正在查看该软件的早期版本的文档。 切换到最新稳定版本。

9. 编写第一个mutation


在本节中,您将编写第一个用于登录后端的 mutation。 以登录到后端。

mutation 用于在服务器上更改数据。在此处,登录 mutation 将根据您的电子邮件地址创建一个会话。

注意:您登录到此特定服务器的方式可能与登录您自己的服务器的方式不同。登录通常由 中间件 或与 GraphQL 完全分开的一层处理,如 Oauth。此外,请记住,典型的身份验证流程通常需要密码,但在此教程中,任何人只要提供有效的电子邮件地址即可预订航班!

在Sandboxes Explorer中设计您mutation

打开 您的Sandboxes Explorer,并点击加号添加新标签。接下来,点击Schema图标返回查看您的模式,并选择 "” 来查看您的mutation列表:

The list of available mutations

向下滚动查看login mutation

The definition of login in the schema

在浏览器的右侧点击播放按钮,打开该 mutation。打开后,点击加号添加操作:

The login mutation after initially being added

请注意红色错误提示 - 这是由于 mutation 返回的类型是 User,这不是一个 类型:你需要选择 中 mutation 将返回哪个。就我们的目的而言,我们只需要 token ,因此通过点击它旁边的加号来添加它。

你会发现 email 也没有自动添加为一个 ,即使它似乎没有默认值:这是因为 email 的类型是 String - 在.GraphQL中,这意味着它不是必需的(尽管显然没有它也走不远)。

点击 email 参数旁边的加号将其添加到参数中:

The operation with the email argument

你还会注意到,沙箱探索器已经在你“变量”部分添加了一个 来匹配登录电子邮件。

点击你的 mutation 中的 按钮。你会看到,由于你为电子邮件地址发送了 null,你得到登录的 null

Results of passing a null email

现在,将 null 替换为 部分的实际电子邮件地址:

(沙箱探索器)
{ "email": "[email protected]" }

按下提交操作按钮,这次你将获得实际响应:

Results of passing an actual email

接下来,复制操作,可以手动操作,也可以使用三点菜单的“复制操作”选项。

将变异添加到项目中

现在,你的变异起作用了,将其添加到项目中。创建一个名为Login.graphql的文件,并将其放置在schema.graphqls以及你的其他GraphQL文件旁边,并将变异的内容粘贴进去:

app/src/main/graphql/Login.graphql
mutation Login($email: String!) {
login(email: $email) {
token
}
}

请注意:我们还将email变量标记为非空值,通过在类型后添加!来实现,因为我们总是希望传递它的值。

构建你的项目以生成LoginMutation类。

将提交按钮连接到您的变异

登录后返回上一屏幕,请在Login组合中添加一个navigateBacklambda参数:

app/src/main/java/com/example/rocketreserver/Login.kt
@Composable
fun Login(navigateBack: () -> Unit) {

同样,它应该在MainActivity中初始化:

app/src/main/java/com/example/rocketreserver/MainActivity.kt
composable(route = NavigationDestinations.LOGIN) {
Login(
navigateBack = {
navController.popBackStack()
}
)
}

回退到Login.kt,并创建一个执行登录变异的函数:

app/src/main/java/com/example/rocketreserver/Login.kt
private suspend fun login(email: String): Boolean {
val response = try {
apolloClient.mutation(LoginMutation(email = email)).execute()
} catch (e: ApolloException) {
Log.w("Login", "Failed to login", e)
return false
}
if (response.hasErrors()) {
Log.w("Login", "Failed to login: ${response.errors?.get(0)?.message}")
return false
}
val token = response.data?.login?.token
if (token == null) {
Log.w("Login", "Failed to login: no token returned by the backend")
return false
}
TokenRepository.setToken(token)
return true
}

可能的错误情况已处理,并返回一个布尔值以指示登录是否成功。如果是,则将令牌保存在TokenRepository中。

请注意,该函数标记为suspend,因此需要从协程中调用。要做到这一点,请在Login中声明一个作用域:

app/src/main/java/com/example/rocketreserver/Login.kt
// Submit button
val scope = rememberCoroutineScope()

然后,在 onClick 匿名函数中,将 TODO 替换为对 login() 的调用,并处理结果:

app/src/main/java/com/example/rocketreserver/Login.kt
Button(
modifier = Modifier
.padding(top = 32.dp)
.fillMaxWidth(),
onClick = {
scope.launch {
val ok = login(email)
if (ok) navigateBack()
}
}
) {
Text(text = "Submit")
}

为了改善用户体验,添加一个加载指示器,在登录进行时显示(同时禁用按钮以避免多次点击)。

app/src/main/java/com/example/rocketreserver/Login.kt
// Submit button
var loading by remember { mutableStateOf(false) }
val scope = rememberCoroutineScope()
Button(
modifier = Modifier
.padding(top = 32.dp)
.fillMaxWidth(),
enabled = !loading,
onClick = {
loading = true
scope.launch {
val ok = login(email)
loading = false
if (ok) navigateBack()
}
}
) {
if (loading) {
Loading()
} else {
Text(text = "Submit")
}
}

测试登录

前往详情页面,点击 Book,然后在登录页面输入您的电子邮件并点击 提交。现在您有一个令牌,允许您进行操作

The login screen

在下一节中,您将 使用认证操作来预订航班

上一页
8. 添加详情视图
下一页
10. 认证您的操作
评价文章评价Edit on GitHubEdit论坛Discord

©2024由Apollo Graph Inc.(简称Apollo GraphQL)运营。

隐私政策

公司