如何编写突变解析器来更改对象的一个或多个特定值?
How to write a mutation resolver to change one or more specific values of an object?
期望一个解析器处理一个或多个对象值的任意组合的输入似乎是合理的。我不应该为 'title'、'published'、'author' 等编写单独的解析器,对吧?
这是我的示例对象:
let books = [
{
title: 'Clean Code',
published: 2008,
author: 'Robert Martin',
id: 'afa5b6f4-344d-11e9-a414-719c6709cf8e',
genres: ['refactoring'],
},
{
title: 'Agile software development',
published: 2002,
author: 'Robert Martin',
id: 'afa5b6f5-344d-11e9-a414-719c6709cf9e',
genres: ['agile', 'patterns', 'design'],
},
]
typeDefs:
const typeDefs = gql`
type Book {
title: String
published: Int
author: String
id: ID
genres: [String]
}
type Query {
bookCount: Int!
allBooks(title: String, author: String, genre: String): [Book]
findBooks(title: String!): Book
}
type Mutation {
addBook(
title: String!
published: Int
author: String!
genres: [String]
): Book
editBook(
id: ID
title: String
published: Int
author: String
genres: [String]
): Book
}
`
这是我目前拥有的解析器:
Mutation: {
editBook: (_, args) => {
const book = books.find(b => b.id === args.id)
if (!book) {
return null
}
const updatedBook = {
...book,
title: args.title,
author: args.author,
published: args.published,
genres: [args.genres],
}
books = books.map(b => (
b.id === args.id ? updatedBook : b))
return updatedBook
},
}
这是当前发生的事情。
原始对象:
"allBooks": [
{
"id": "afa5b6f4-344d-11e9-a414-719c6709cf8e",
"title": "Clean Code",
"author": "Robert Martin",
"published": 2008,
"genres": [
"refactoring"
]
},
{...}
]
突变查询:
mutation {
editBook(id:"afa5b6f4-344d-11e9-a414-719c6709cf8e", title:"changed"){
id
title
author
published
genres
}
}
Returns这个:
{
"data": {
"editBook": {
"id": "afa5b6f4-344d-11e9-a414-719c6709cf8e",
"title": "changed",
"author": null,
"published": null,
"genres": [
null
]
}
}
}
如何编写解析器来更改对象的一个或多个值,而不将未指定的值更改为 'null'?
我承认,我的 javascript 技能相当不稳定,我猜答案在于更多 eloquent 映射函数,但由于代码在 graphql 模式中运行模块,它不处理 console.log
所以故障排除是有问题的。任何解决该问题的建议也将非常有帮助,这样我就可以更好地解决自己的问题。
两点
无需使用地图或重新分配 books
。因为 book
变量是对 books 数组中对象的引用,所以您可以改变它(但不能重新分配它)并且您将改变数组中的对象。有关详细信息,请参阅 this question。
const book = books.find(b => b.id === args.id)
if (book) {
// you cannot reassign book and still have the original value change,
// but you can mutate it
book.title = args.title
book.author = args.author
book.published = args.published
book.genres = args.genres
}
return book
要仅更改 args 中存在的值,您有一些选择:
如果第一个值是假的,您可以使用逻辑或运算符 (||
) 提供另一个要分配的值。此处,book.title
仅在 args.title
为 undefined
、null
、0
、NaN
、""
或 false
.
book.title = args.title || book.title
您可以使用 Object.assign,它将属性从一个对象复制到另一个对象。由于 args
将丢失那些未提供的属性,您可以像下面的代码片段那样做。这更加优雅和简洁,但仅当您的参数名称与您的 属性 名称匹配时才有效。
Object.assign(book, args)
您可以遍历 args
对象。如果您有一个或多个参数与 book
:
的属性不匹配,这可能更可取
Object.keys(args).forEach(argName => {
const argValue = args[argName]
book[argName] = argValue
})
综合起来,我们可能会做:
const book = books.find(b => b.id === args.id)
if (book) {
Object.assign(book, args)
}
return book
期望一个解析器处理一个或多个对象值的任意组合的输入似乎是合理的。我不应该为 'title'、'published'、'author' 等编写单独的解析器,对吧?
这是我的示例对象:
let books = [
{
title: 'Clean Code',
published: 2008,
author: 'Robert Martin',
id: 'afa5b6f4-344d-11e9-a414-719c6709cf8e',
genres: ['refactoring'],
},
{
title: 'Agile software development',
published: 2002,
author: 'Robert Martin',
id: 'afa5b6f5-344d-11e9-a414-719c6709cf9e',
genres: ['agile', 'patterns', 'design'],
},
]
typeDefs:
const typeDefs = gql`
type Book {
title: String
published: Int
author: String
id: ID
genres: [String]
}
type Query {
bookCount: Int!
allBooks(title: String, author: String, genre: String): [Book]
findBooks(title: String!): Book
}
type Mutation {
addBook(
title: String!
published: Int
author: String!
genres: [String]
): Book
editBook(
id: ID
title: String
published: Int
author: String
genres: [String]
): Book
}
`
这是我目前拥有的解析器:
Mutation: {
editBook: (_, args) => {
const book = books.find(b => b.id === args.id)
if (!book) {
return null
}
const updatedBook = {
...book,
title: args.title,
author: args.author,
published: args.published,
genres: [args.genres],
}
books = books.map(b => (
b.id === args.id ? updatedBook : b))
return updatedBook
},
}
这是当前发生的事情。
原始对象:
"allBooks": [
{
"id": "afa5b6f4-344d-11e9-a414-719c6709cf8e",
"title": "Clean Code",
"author": "Robert Martin",
"published": 2008,
"genres": [
"refactoring"
]
},
{...}
]
突变查询:
mutation {
editBook(id:"afa5b6f4-344d-11e9-a414-719c6709cf8e", title:"changed"){
id
title
author
published
genres
}
}
Returns这个:
{
"data": {
"editBook": {
"id": "afa5b6f4-344d-11e9-a414-719c6709cf8e",
"title": "changed",
"author": null,
"published": null,
"genres": [
null
]
}
}
}
如何编写解析器来更改对象的一个或多个值,而不将未指定的值更改为 'null'?
我承认,我的 javascript 技能相当不稳定,我猜答案在于更多 eloquent 映射函数,但由于代码在 graphql 模式中运行模块,它不处理 console.log
所以故障排除是有问题的。任何解决该问题的建议也将非常有帮助,这样我就可以更好地解决自己的问题。
两点
无需使用地图或重新分配 books
。因为 book
变量是对 books 数组中对象的引用,所以您可以改变它(但不能重新分配它)并且您将改变数组中的对象。有关详细信息,请参阅 this question。
const book = books.find(b => b.id === args.id)
if (book) {
// you cannot reassign book and still have the original value change,
// but you can mutate it
book.title = args.title
book.author = args.author
book.published = args.published
book.genres = args.genres
}
return book
要仅更改 args 中存在的值,您有一些选择:
如果第一个值是假的,您可以使用逻辑或运算符 (||
) 提供另一个要分配的值。此处,book.title
仅在 args.title
为 undefined
、null
、0
、NaN
、""
或 false
.
book.title = args.title || book.title
您可以使用 Object.assign,它将属性从一个对象复制到另一个对象。由于 args
将丢失那些未提供的属性,您可以像下面的代码片段那样做。这更加优雅和简洁,但仅当您的参数名称与您的 属性 名称匹配时才有效。
Object.assign(book, args)
您可以遍历 args
对象。如果您有一个或多个参数与 book
:
Object.keys(args).forEach(argName => {
const argValue = args[argName]
book[argName] = argValue
})
综合起来,我们可能会做:
const book = books.find(b => b.id === args.id)
if (book) {
Object.assign(book, args)
}
return book