我是 GraphQL 的初学者,正在学习以下示例
https://graphql.com/learn/mutations/
**Mutation definition:**
type Mutation {
updateProducePrice(producePriceInput: UpdateProducePriceInput!): UpdateProducePriceResponse
}
input UpdateProducePriceInput {
produceItemId: ID!
newPrice: Int!
}
type UpdateProducePriceResponse {
code: Int!
success: Boolean!
message: String!
produceItem: Produce
}
**Mutation request:**
mutation UpdateProducePrice($producePriceInputVariable: UpdateProducePriceInput!) {
updateProducePrice(producePriceInput: $producePriceInputVariable) {
success
message
produceItem {
name
price
}
}
}
**Variable input:**
{
"producePriceInputVariable": {
"produceItemId": "F4",
"newPrice": 113
}
}
**Response:**
{
"data": {
"updateProducePrice": {
"success": true,
"message": "Price successfully updated for orange, from 41 to 113",
"produceItem": {
"name": "orange",
"price": 113
}
}
}
}
由于produceItem:Produce
在中定义 type UpdateProducePriceResponse
,并且突变返回Produce 类型的name
和price
(从 41 更新为 113),给定 Id 和 newPrice 作为输入。
newPrice 的值如何传递给 Produce 类型中定义的价格字段?我读过有关解析器的文章,但不明白其内部是如何运作的。
ELI5 的答案没有涉及细节:
每个对象类型的每个字段都有一个“解析器”。解析器是一个具有四个参数的函数:
parent
:这是“对象的当前状态”,由在它之前运行的解析器提供(这很快就会有意义)args
:如果架构中定义了参数,则请求发送的值将在此处传递context
:当请求开始时,您定义此对象,它会告诉函数有关请求的元信息(您应该在此处查看当前用户)。每个解析器都使用相同的值。info
:这是有关操作状态的信息。它将包括解析器所针对的字段的名称、从该字段一直到根的路径等。让我们使用一个精简的模式来展示它是如何工作的(请注意,这个模式作为示例很好,但不遵循最佳实践):
现在我们要提出这个请求:
首先,GraphQL 引擎会查看您的入口点,即
Mutation.createUser
。它会检查是否存在包含“Mutation”的解析器对象,并检查该对象上是否有“createUser”函数。我将使用所有同步代码,这样 await/async/promises 就不会造成混淆。有一个 Mutation 解析器对象,它有一个名为 的属性
createUser
,它是一个函数。它调用此函数并获取响应。它还知道该函数的响应类型必须是“User”,因此它添加了一个名为 的属性__typename
。这是当前数据:太棒了。现在它会检查您在“createUser”返回的对象上请求的字段。您请求
__typename 是 User,因此现在引擎会检查您是否有针对以下每个类型的解析器:
有一个
User
解析器对象。User.id
;调用它User.birthDate
;调用它User.name
,因此使用默认解析器。由于您没有为 传递函数User.name
,因此它只会返回parent.name
。以下是“默认解析器”的一般概念:你要求
User.createdDate
,因此它将使用默认解析器。由于parent
没有createdDate
(您没有从 createUser 返回),因此它返回undefined
。GraphQL 引擎现在必须检查是否null
允许(将 undefined 视为)createdDate
。您的架构没有感叹号,因此现在您的返回数据如下所示:看上去已经完成了,但其实并没有。现在进入下一个级别。您要求输入哪些字段
birthDate
?并且 __typename 是
Date
...。解析器是否具有
Date
这些属性的功能?假设没有。因此将使用默认解析器。现在经过所有解析器之后你的最终 json 是:
** 附注:每种类型和每个属性的工作原理大致相同:
createUser
在同一个操作中有两个调用,则它们必须一个接一个地发生,但name
、id
和birthDate
都可以并行运行。