Reputation: 14774
I am using Vue.js with Vue-Apollo and initiating a User mutation to sign in a user. I am using the graph.cool service.
I have a request pipeline function setup to catch some errors, like an invalid email.
When the request is made with bad / invalid input, my error catch()
fires (as expected) and in the network tab I can see the JSON for the custom errors messages. But how do I access these errors / response from within the catch if an error is triggered from graph.cool?
Example:
signin () {
const email = this.email
const password = this.password
this.$apollo.mutate({
mutation: signinMutation,
variables: {
email,
password
}
})
.then((data) => {
// This never fires on an error, so I can't
// show the user the errors in the network repsonse.
console.log(data)
})
.catch((error) => {
// Error in this part fires in the console
// but I'm unable to show the JSON response
// errors because the 'then()' above doesn't execute.
console.error(error)
})
}
I get the following error for an unrecognised user:
Error: GraphQL error: No user found with that information at new ApolloError (eval at (app.js:956), :34:28) at eval (eval at (app.js:1353), :139:33) at
Any idea how to show the errors in the response from within the catch()
?
I can literally see the errors I want to show to the user in the response on the network tab here:
...but I can't figure out how to do it.
Any help much appreciated! Thank you.
Upvotes: 5
Views: 3671
Reputation: 14774
So, it looks as though I was handling this the wrong way by barking up the wrong tree.
The key to the answer was examining the error from the .catch()
with console.dir(error)
. This revealed some useful keys...namely:
error.graphQLErrors[0]
So all in all, the corrected code looks like this:
signin () {
const email = this.email
const password = this.password
this.$apollo.mutate({
mutation: signinMutation,
variables: {
email,
password
}
})
.then(data => {
console.log(data)
})
.catch(error => {
console.log(graphQLErrorMessages(error))
})
}
The graphQLErrorMessages()
function is a helper I wrote, so that I can reuse this in other .catch()
blocks:
function graphQLErrorMessages (errorsFromCatch) {
const errors = errorsFromCatch.graphQLErrors[0]
const messages = []
if (errors.hasOwnProperty('functionError')) {
const customErrors = JSON.parse(errors.functionError)
messages.push(...customErrors.errors)
} else {
messages.push(errors.message)
}
return messages
}
It returns an array of error messages (which is what I needed) but you could format this any way you like.
It might be a little https://graph.cool specific in its logic (I'm not so sure), but I hope this ends up helping someone also stuck in a similar situation!
Upvotes: 7
Reputation: 3780
I may be misunderstanding your question so please comment and correct me if I am but it looks like you may be having trouble with Promises more than with Vue or GraphQL.
Just like in a try...catch
statement, once you catch an error, your program will continue to execute unless you re-throw the error. For example:
This Catches
try {
codeThatThrowsAnError();
} catch(e) {
// Do Nothing
}
This re-throws
try {
codeThatThrowsAnError();
} catch(e) {
throw new Error("Err 135: I failed")
}
Similarly, in Promise land, you can either catch the error and move like you have in your example, or you can re-throw. What you may be missing is that anything you return from a catch statement will be used in the next then
. For example:
somethingReturningAFailedPromise()
.then(doWork)
.catch((err) => {
return "I'm a New Value"
})
.then(console.log)
//=> "I'm a New Value"
It sounds to me like what you need is a data function that is more resilient to failure like the following:
const getUserProfile = (id) => {
return fetchUserData(id)
.catch((err) => {
logError(err);
return {};
})
}
Upvotes: -1