Mongodb 阿波罗反应图:Can';对于不可为null的对象,t返回null
我遇到了一个奇怪的现象,当我运行类似的突变时,返回的是什么。我正在学习这个堆栈,我用mongoose作为我的数据库层来实现mongodb 我有两个简单的突变。创建一个用户并将其添加到数据库或注册表中。另一个在创建初始用户对象之后添加一个概要文件pic 两个解析器都返回完整的用户对象,这对于更新ui、存储等很好,我正计划实现订阅,因此重要的是我要返回新数据 我在用graphiql解决问题时遇到了一个奇怪的问题。即使图像url被保存到数据库中,我的更新解析程序仍返回null。寄存器解析程序正在返回所有用户字段 在控制台记录解析程序中的返回对象时,两个函数都返回了完整的用户对象 当我试图使返回对象不可为null时,我会得到一个错误:更新解析程序不能为不可为null返回null 我的解析器最初使用findOneAndUpdate和一个实际上返回用户对象的回调。是的,我仍然是空的。奇怪 我将解析器改为更手动的方法。我使用findOne查找现有用户,传入用户id,然后显式地说user.profilePic=“url of pic”,并调用整个用户对象的save,然后在回调中将用户对象返回给该用户对象。砰的一声,那就行了 那么是什么导致了这一现象呢?我最初的感觉是,这与时间有关,也就是不等待回调……我真的不明白为什么我的第一种方法不起作用,而我的第二种方法起作用。我将附上这两个方面的代码,也许有人对计时有更深入的了解,或者可能异步函数可以插话。也许我需要将我的风格从回调更新为承诺或异步等待Mongodb 阿波罗反应图:Can';对于不可为null的对象,t返回null,mongodb,mongoose,graphql,graphql-js,Mongodb,Mongoose,Graphql,Graphql Js,我遇到了一个奇怪的现象,当我运行类似的突变时,返回的是什么。我正在学习这个堆栈,我用mongoose作为我的数据库层来实现mongodb 我有两个简单的突变。创建一个用户并将其添加到数据库或注册表中。另一个在创建初始用户对象之后添加一个概要文件pic 两个解析器都返回完整的用户对象,这对于更新ui、存储等很好,我正计划实现订阅,因此重要的是我要返回新数据 我在用graphiql解决问题时遇到了一个奇怪的问题。即使图像url被保存到数据库中,我的更新解析程序仍返回null。寄存器解析程序正在返回所
//this one doesnt work
addProfilePic: (root, { input }, context) => {
let update = { profilePic: input.profilePic };
let query = { id: input.id };
let options = { new: true, upsert: true};
let callback = ((err, user) => {
if(err) console.log(err.message);
return user;
})
return updatedUser = User.findOneAndUpdate(query, update, options, callback)
}
//this one works, but returns old user object to client...
//so really, no, it doesn't work
addProfilePic: (root, { input }, context) => {
return User.findOne({id: input.id}, ((err,user) => {
if(err)console.log(err);
if(user){
user.profilePic = input.profilePic;
user.save((err) => {
if(err)console.log(err);
console.log(user);
return user;
})
}
})
})
注意:在传递上下文时,当我实际实现时,我将从上下文中获取id,其中包含用户登录时的id。
注意:这些很快就是很酷的工具,但还有很多东西需要学习,特别是对于那些有3个月总编码经验的人来说,比如我…不管文档怎么说,当包含回调时,
findOneAndUpdate
返回未定义的。另一方面,findOne
返回一个查询对象。这里的问题是,当您传递回调时,您的目的是处理作为参数传递给回调的值,而不是处理调用的返回值
使用GraphQL,解析程序可以返回解析为该值的值或承诺。findOne
返回的查询对象不是承诺,而是“thenable”,因此从某种意义上讲,您可以通过这种方式“逃脱”。但是,我怀疑如果您查看GraphQL实际返回的内容,您会发现它返回的是原始用户对象,而不是保存的对象
正如您所猜测的,有一种更好的方法:)
要让猫鼬返回承诺,您需要:
.exec()
追加到调用的末尾addProfilePic: (root, { input }, context) => {
let update = { profilePic: input.profilePic };
let query = { id: input.id };
let options = { new: true, upsert: true};
return User.findOneAndUpdate(query, update, options).exec()
}
要让您走上正确的道路,请注意以下几点:
你会注意到我在上面的代码中没有做任何错误处理。这是因为GraphQL实际上会为您捕获这些错误,并将它们包含在响应中。但是,如果您想提供其他错误信息,或混淆返回给客户端的详细信息,您可以将catch()
附加到调用中,修改其中的错误,然后将其抛出
现在您正在返回一个承诺,您可以使用then()
如果需要处理查询结果,请记住返回里面的值
return User.findOneAndUpdate(query, update, options).exec()
.then(user => {
console.log(user)
// you could modify the object being handed to GraphQL here
return user // IF you use a then, make sure you return the value!!
})
最后,如果最终使用回调,请注意,与承诺不同,回调中的返回语句没有任何作用(至少在本例中没有)。因为它们是异步的,所以您无法以某种方式将调用它们的值返回到原始调用(不是不将所有内容包装在承诺中,如果您已经返回了承诺,那么这条路径就不值得采用)。不管文档怎么说,当您包含回调时,
findOneAndUpdate
返回未定义的。另一方面,findOne
返回一个查询对象。这里的问题是,当您传递回调时,您的目的是处理作为参数传递给回调的值,而不是处理调用的返回值
使用GraphQL,解析程序可以返回解析为该值的值或承诺。findOne
返回的查询对象不是承诺,而是“thenable”,因此从某种意义上讲,您可以通过这种方式“逃脱”。但是,我怀疑如果您查看GraphQL实际返回的内容,您会发现它返回的是原始用户对象,而不是保存的对象
正如您所猜测的,有一种更好的方法:)
要让猫鼬返回承诺,您需要:
.exec()
追加到调用的末尾addProfilePic: (root, { input }, context) => {
let update = { profilePic: input.profilePic };
let query = { id: input.id };
let options = { new: true, upsert: true};
return User.findOneAndUpdate(query, update, options).exec()
}
要让您走上正确的道路,请注意以下几点:
你会注意到我在上面的代码中没有做任何错误处理。这是因为GraphQL实际上会为您捕获这些错误,并将它们包含在响应中。但是,如果您想提供其他错误信息,或混淆返回给客户端的详细信息,您可以将catch()
附加到调用中,修改其中的错误,然后将其抛出
现在,您正在返回一个承诺,如果您需要工作,可以使用then()