期待一个解析器处理一个或多个对象值的任意组合的输入似乎是合理的。我不必为“标题”,“已发布”,“作者”等编写单独的解析器,对吗?
这是我的示例对象:
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
}
}
返回此:
{
"data": {
"editBook": {
"id": "afa5b6f4-344d-11e9-a414-719c6709cf8e",
"title": "changed",
"author": null,
"published": null,
"genres": [
null
]
}
}
}
我如何编写解析器来更改一个或多个对象的值,而不将未指定的值更改为'null'?
我承认,我的JavaScript技能相当不稳定,我猜测答案在于更加雄辩的map函数,但是由于代码在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中存在的值,您可以使用一些选项:
如果第一个值为false,则可以使用逻辑OR运算符(||
)提供另一个值进行分配。在此,仅当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[bookProperty] = argValue })
将它们放在一起,我们可能会做:
const book = books.find(b => b.id === args.id) if (book) { Object.assign(book, args) } return book