mongodb - Graphql Apollo React: Can't Return null for non nullable -
i have come across oddity in gets returned when run similar mutations. learning stack, , implement mongodb mongoose database layer.
i have 2 simple mutations. 1 creates user , adds database aka register. other adds profile pic after initial user object created.
both resolvers return full user object, nice updating ui, store, etc, planning on implementing subscriptions important new data back.
i working thing out graphiql , ran weird problem. update resolver returning null though image url getting saved db. register resolver returning user fields.
upon console logging return objects in resolvers, both functions returning full user object.
when tried make return object non nullable error cant return null non nullable update resolver.
my resolver using findoneandupdate callback did in fact return user object. , yes, still getting null. weird.
i changed resolver instead more manual approach. existing user findone passing in user id, explicitly saying user.profilepic = "url of pic" , calling save of whole user object , returning user object in callback that. , boom, works!
so causing this? initial feeling has timing somehow aka not waiting callback....i dont understand why first approach doesn't work , second does. attach code both maybe deeper understanding of timing or possibly async functions can chime in. maybe need update style callbacks promises or async await.
//this 1 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 1 works, returns old user object client... //so really, no, 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; }) } }) })
note: passing in context, when implement id context, contains user when logged in. note: these cool tools, lot learn, 3 months total coding exp...ie me...
despite docs say, when include callback, findoneandupdate
returns undefined. on other hand, findone
returns query object. problem here when pass callback, intent handle values passed callback arguments, not deal whatever call's return value is.
with graphql, resolver can return value or promise resolves value. query object returned findone
isn't promise, "thenable" , in sense "getting away" doing things way. however, suspect if @ what's being returned graphql, you'll find it's returning original user object, not saved one.
as conjectured there better way :)
to mongoose
return promise, need to:
- drop callback altogether
- append
.exec()
end of call
now resolver looks this:
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() }
a couple of additional notes on right path:
you'll notice don't error handling in code above. because graphql catch errors , include them in response. however, if wanted either provide additional error information, or obfuscate details being returned client, can append catch()
call, modify error inside , throw back.
now you're returning promise, can use then()
if need work query result, remember return value inside!
return user.findoneandupdate(query, update, options).exec() .then(user => { console.log(user) // modify object being handed graphql here return user // if use then, make sure return value!! })
lastly, if end using callbacks, aware that, unlike promises, return statements inside them don't (at least not in case). because asynchronous, there's no way can somehow return values called origin call (not without wrapping inside promise , that's path that's not worth taking if can have promise returned).
Comments
Post a Comment